回文自动机
- 如果不考虑空间回文自动机几乎可以替代 manacher 吧
构造
- 比较简单,就直接放代码了
const int N=1e6+10;
char S[N];
int n,t[N][26],fail[N],len[N],num[N];
int tot=1,cur,last=0;
inline int getpos(int x,int i) {
while(i-len[x]-1<1 || S[i-len[x]-1]!=S[i]) x=fail[x];
return x;
}
signed main(){
scanf("%s",S+1);
n=strlen(S+1);
fail[0]=1;len[1]=-1;
FOR(i,1,n) {
if(i>1) S[i]=(S[i]+last-97)%26+97;
int pos=getpos(cur,i);
if(!t[pos][S[i]-'a']) {
fail[++tot]=t[getpos(fail[pos],i)][S[i]-'a'];
len[tot]=len[pos]+2;
num[tot]=num[fail[tot]]+1;
t[pos][S[i]-'a']=tot;
}
cur=t[pos][S[i]-'a'];
cout<<(last=num[cur])<<' ';
}
return 0;
}
有趣的性质
-
对于插入一般我们都是在末尾插入,但是其实也可以同时进行从头插入
-
因为可以发现整个字符串的不管是前后维护的回文子串是一样的,所以对于前/后缀都维护一下最长的回文子串所在的结点就可以了