构建
两棵Trie树,分别记录长度为奇数/偶数的回文串。fail指针指向对侧的树。先通过跳前一个位置的fail找到当前位置向前的最长回文串,并新建节点表示该串。然后,对跳该串的父节点的fail以确定该串的fail。
注意
- 初始状态
fa[0] =1, fa[1] =0, len[0]=0, len[1]=-1;
洛谷模板
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e6+10;
int len[N],fail[N],ch[N][26],cnt[N];
char s[N];
int tot=1,last=0;
void init()
{
fail[0]=1; fail[1]=0;
len[0]=0; len[1]=-1;
}
void extend(int x,int l)
{
int u=last;
while(s[l-len[u]-1]!=s[l]) u=fail[u];
if(ch[u][x]==0)
{
int now=++tot;
len[now]=len[u]+2;
int v=fail[u];
while(s[l-len[v]-1]!=s[l]) v=fail[v];
fail[now]=ch[v][x];
ch[u][x]=now;
cnt[now]=cnt[fail[now]]+1;
}
last=ch[u][x];
}
int main()
{
scanf("%s",s+1);
int n=strlen(s+1);
int ans=0;
init();
for(int i=1;i<=n;i++)
{
s[i]=(s[i]-97+ans)%26+97;
extend(s[i]-'a',i);
ans=cnt[last];
printf("%d ",ans);
}
return 0;
}