問題の意味
各ノードについて考える\(X \)メンテナンス\(lastpos_x \)を表し(X \)\まず接尾文字列パリンドロームの\(LEN \ leqslant len_x / 2 \) とエネルギーと\(X \)列挙ノード回文文字列の後の試合の最後の文字は、その時点の合法性を決定します。
探している\(lastpos_x \) :
もし新しいノード\(X \)を満足\(len_x \ leqslant 2 \) 、次いで\(lastpos_x fail_x = \) 。
そうでない場合は、\(X \)父ノードがジャンプアップ、あなたは裁判官に合わせて踊ることができます。
コード:
#include<bits/stdc++.h>
using namespace std;
const int maxn=500010;
int n,ans;
char s[maxn];
struct PA
{
int last,tot;
int fail[maxn],len[maxn],lastpos[maxn];
int ch[maxn][30];
PA(){tot=1;fail[0]=1;len[1]=-1;}
inline int getfail(int x,int pos,char* s)
{
s[0]='#';
while(s[pos-len[x]-1]!=s[pos])x=fail[x];
return x;
}
inline void build(char* s,int n)
{
s[0]='#';
for(int i=1;i<=n;i++)
{
int c=s[i]-'a';
int p=getfail(last,i,s);
if(!ch[p][c])
{
int q=++tot;len[q]=len[p]+2;
int tmp=getfail(fail[p],i,s);
fail[q]=ch[tmp][c];ch[p][c]=q;
if(len[q]<=2)lastpos[q]=fail[q];
else
{
tmp=lastpos[p];
while(s[i-len[tmp]-1]!=s[i]||((len[tmp]+2)<<1)>len[q])tmp=fail[tmp];
lastpos[q]=ch[tmp][c];
}
}
last=ch[p][c];
}
}
}pa;
int main()
{
//freopen("test.in","r",stdin);
//freopen("test.out","w",stdout);
scanf("%d%s",&n,s+1);
pa.build(s,n);
for(int i=2;i<=pa.tot;i++)
if((pa.len[pa.lastpos[i]]<<1)==pa.len[i]&&pa.len[pa.lastpos[i]]%2==0)
ans=max(ans,pa.len[i]);
printf("%d",ans);
return 0;
}