BZOJ2342: [Shoi2011]双倍回文

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2342

回文树然后我们把fail树建出来,然后对于0和1进行dfs就可以了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 500500
#define eps 1e-6
using namespace std;
struct data{int obj,pre;
}e[maxn*2];
int ans,n,cnt,tot,cur,last,tot2;
char ch[maxn];
int fail[maxn],s[maxn],to[maxn][30],len[maxn],b[maxn],head[maxn];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
void init(){
    len[0]=0; len[1]=-1; fail[0]=1; tot=1; s[0]=-1;
}
void add(int c){
    s[++n]=c;
    int cur,tmp,now;
    for (cur=last;s[n-len[cur]-1]!=s[n];cur=fail[cur]);
    if (!to[cur][c]){
        len[++tot]=len[cur]+2; now=tot;
        for (tmp=fail[cur];s[n-len[tmp]-1]!=s[n];tmp=fail[tmp]);
        fail[now]=to[tmp][c];
        to[cur][c]=now;
    } last=to[cur][c];
}
void insert(int x,int y){
    e[++tot2].obj=y; e[tot2].pre=head[x]; head[x]=tot2;
}
void dfs(int u){
    if (len[u]>0&&len[u]%4==0&&b[len[u]/2]) ans=max(ans,len[u]);
    b[len[u]]=1;
    for (int j=head[u];j;j=e[j].pre){
        int v=e[j].obj; 
        dfs(v);
    } 
    b[len[u]]=0;
}
int main(){
    cnt=read(); 
    scanf("%s",ch+1);
    init();
    rep(i,1,cnt){
        add(ch[i]-'a'+1);
    }
    rep(i,2,tot) insert(fail[i],i);
    dfs(0); dfs(1);
    printf("%d\n",ans);
    return 0;
}

 

posted on 2015-12-01 14:27  ctlchild  阅读(177)  评论(0编辑  收藏  举报

导航