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; 
}

  

posted @ 2020-01-02 08:09  EM-LGH  阅读(154)  评论(0编辑  收藏  举报