版权声明:欢迎转载(请附带原链接)ヾ(๑╹◡╹)ノ" https://blog.csdn.net/corsica6/article/details/84930970
传送门:bzoj2342
题解
回文自动机很好做,但这里讲一下manacher的做法。
设偶回文中心 的回文半径为 。
枚举回文中心 ,找到最小的 满足: 且
将回文中心按 升序排序并加入set, 枚举 时 所有 ,二分找出现存的最小的 即可。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+100;
int n,m,f[N],rk[N],nt[N],ans;
char s[N],t[N];
set<int>st;
inline void manacher()
{
int i,j,ct=0,mx=0;
for(i=1;i<=n;++i){
for(j=mx>i?min(mx-i,f[(ct<<1)-i]):1;t[i-j]==t[i+j];++j);
f[i]=j;if(i+j>mx) mx=i+j,ct=i;
}m=0;
for(i=3;i<=n;i+=2) nt[++m]=f[i]>>1;
m--;
}
inline bool cmp(const int&x,const int&y){return x+nt[x]<y+nt[y];}
int main(){
int i,j,x;
scanf("%d%s",&m,s+1);
t[0]='!';
for(i=1;i<=m;++i) t[++n]='#',t[++n]=s[i];
t[++n]='#';t[++n]='?';
manacher();for(i=1;i<=m;++i) rk[i]=i,st.insert(i);
sort(rk+1,rk+m+1,cmp);
set<int>::iterator it;
for(i=j=1;i<=m;++i){
for(;j<=m && rk[j]+nt[rk[j]]<i;++j) st.erase(rk[j]);
x=*st.lower_bound(i-(nt[i]>>1));ans=max(ans,(i-x)<<2);
}
printf("%d\n",ans);
return 0;
}