a[0].len =0, a[1].len =-1;
a[0].fail =1;
la =0;//上一个字符的最长回文后缀
已经构造好了前
i
−
1
i-1
i−1个字符的回文树,当前需要加入第
i
i
i个字符
c
c
c。
从上一个字符的最长回文后缀开始,不断往fail链走,直到能够满足
c
=
s
t
i
−
l
e
n
−
1
c=st_{i-len-1}
c=sti−len−1,即直到某个串的左边的字符和它右边的字符
c
c
c相同。
那么这个点的
c
c
c儿子即为当前的最长回文后缀,注意需要判断
c
c
c儿子是否存在,如果不存在需要添加。
int x = la;while(st[i]!= st[i -1- a[x].len]) x = a[x].fail;if(!a[x].p[st[i]-'a']) a[x].p[st[i]-'a']=++tot;//如果没有儿子则添加
la = a[x].p[st[i]-'a'];
a[la].len = a[x].len +2;
如果新建了一个点,则需要找到这个点的fail指针指向哪里。
类似AC自动机地,从它的父亲的fail开始不断往fail链跳,但是不能像AC自动机一样判断当前点是否有
c
c
c这个儿子,而是判断当前回文串的前一个字符是否为
c
c
c。