回文树复习 注意事项 code

初始有两个根01,分别对应奇偶,长度为0/-1,0的fail是1

如果跳到了1号点,那么新建的点的fail是0

种数=点数-1,某个串结尾的回文子串个数=fail链长度

扩展要考虑匹配以及边界

code

洛谷5496

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int tr[500011][26],fa[500011],sum[500011],Len[500011],n,i,j,k,l,ans,len;
char st[500001],ch;

int main()
{
	#ifdef file
	freopen("luogu5496.in","r",stdin);
	freopen("luogu5496.out","w",stdout);
	#endif
	
	len=1;l=0;
	fa[0]=fa[1]=1;
	Len[0]=0,Len[1]=-1;
	
	ch=getchar();
	while (ch>='a' && ch<='z')
	{
		ch=(ch-97+ans)%26+97;
		
		st[++n]=ch;j=l;
		while (n-Len[l]-1<1 || st[n-Len[l]-1]!=ch) l=fa[l];
		if (!tr[l][ch-'a'])
		{
			tr[l][ch-'a']=++len;Len[len]=Len[l]+2;
			j=fa[l];
			while (n-Len[j]-1<1 || st[n-Len[j]-1]!=ch) j=fa[j];
			
			fa[len]=(j==l)?0:tr[j][ch-'a'];sum[len]=sum[fa[len]]+1;
		}
		l=tr[l][ch-'a'];
		
		ans=sum[l],printf("%d ",ans);
		ch=getchar();
	}
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}