BZOJ 2342: [Shoi2011]双倍回文 回文自动机
建立一个回文自动机,然后开一个桶遍历一下回文树就好了.
code:
#include <cstdio> #include <vector> #include <string> #include <cstring> #include <algorithm> #define N 500007 using namespace std; char S[N]; int tot,last,n,ans; vector<int>G[N]; int ch[N][26],len[N],pre[N],ss[N],bu[N]; int newnode(int x) { return len[++tot]=x,tot; } void Initialize() { pre[0]=1,len[1]=-1,tot=1,ss[0]=-1; for(int i=1;i<=n;++i) ss[i]=S[i]-'a'; } int getfail(int p,int i) { while(ss[i-len[p]-1]!=ss[i]) p=pre[p]; return p; } void extend(int c,int i) { int p=getfail(last,i); if(!ch[p][c]) { int q=newnode(len[p]+2); pre[q]=ch[getfail(pre[p],i)][c]; ch[p][c]=q; } last=ch[p][c]; } void setIO(string s) { freopen((s+".in").c_str(),"r",stdin); } void dfs(int u) { bu[len[u]]++; if((len[u]%4==0)&&bu[len[u]/2]) ans=max(ans,len[u]); for(int i=0;i<G[u].size();++i) dfs(G[u][i]); --bu[len[u]]; } int main() { // setIO("input"); int i,j; scanf("%d%s",&n,S+1); Initialize(); for(i=1;i<=n;++i) extend(ss[i],i); for(i=2;i<=tot;++i) G[pre[i]].push_back(i); dfs(0); printf("%d\n",ans); return 0; }