Luogu P4287 [SHOI2011]双倍回文PAM
多维护一个转移 \(tra[p]\),表示 \(\leq \frac{len[p]}{2}\) 的后缀位于的状态。
最后检查一下是否有 \(len[tra[p]]=len[p]/2 \ \&\&\ len[tra[p]]\%2==0\)
#include<iostream>
#include<cstdio>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=100010;
int n,tot,lst,ans;
int fa[N],c[N][26],len[N],cnt[N],sz[N],tra[N];
char s[N];
inline int jmp(int p,int i)
{while(s[i-len[p]-1]!=s[i]) p=fa[p]; return p;}
inline void add(int ch,int i) {
R p=jmp(lst,i); if(!c[p][ch]) {
R np=++tot; len[np]=len[p]+2;
R t=jmp(fa[p],i);
fa[np]=c[t][ch],c[p][ch]=np;
if(len[np]<=2) tra[np]=fa[np];
else {
t=tra[p];
while(s[i-len[t]-1]!=s[i]||(len[t]+2)*2>len[np]) t=fa[t];
tra[np]=c[t][ch];
}
} lst=c[p][ch];
}
inline void main() {
n=g(),scanf("%s",s+1);
s[0]='#',len[fa[fa[1]=0]=tot=1]=-1;
for(R i=1;i<=n;++i) add(s[i]-'a',i);
for(R i=2;i<=tot;++i)
if(len[tra[i]]*2==len[i]&&!(len[tra[i]]&1))
ans=max(ans,len[i]);
printf("%d\n",ans);
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.16