【BZOJ2342】【SHOI2012】—双倍回文(Pam)
我们发现一个串和其倒置拼一起也是一个回文串
且也是一个回文串
考虑维护一个指针表示和点相同分界点的最长的长度的点
发现这个也可以在构建的时候顺便维护
然后枚举所有的点取即可
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define re register
#define pii pair<int,int>
#define pb push_back
#define fi first
#define se second
#define cs const
#define ll long long
const int N=500005;
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
int ans;
char s[N];
namespace Pam{
int nxt[N][26],fail[N],len[N],half[N];
int tot,last;
inline void init(){
fail[0]=1,len[1]=-1,tot++;
}
inline void insert(int c,int i){
int p=last;
while(s[i-len[p]-1]!=s[i])p=fail[p];
if(!nxt[p][c]){
len[++tot]=len[p]+2;
int k=fail[p];
while(s[i-len[k]-1]!=s[i])k=fail[k];
fail[tot]=nxt[k][c],nxt[p][c]=tot;
k=half[p];
while(s[i]!=s[i-len[k]-1])k=fail[k];
k=nxt[k][c];
while(len[k]*2>len[tot])k=fail[k];
half[tot]=k;
if((len[tot]%4==0)&&(len[k]*2==len[tot]))chemx(ans,len[tot]);
}
last=nxt[p][c];
}
}
int main(){
int len=read();
scanf("%s",s+1),s[0]='$';
Pam::init();
for(int i=1;i<=len;i++)Pam::insert(s[i]-'a',i);
cout<<ans;
}