BZOJ2565: 最长双回文串(回文树)

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

记录一下每个点往前最长延伸位置,正反两遍,枚举分割点。

#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdio>
#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 ll long long
#define maxn 100500
using namespace std;
int len[maxn],cnt[maxn],p1[maxn],p2[maxn],fail[maxn],s[maxn],to[maxn][30];
int n,ans,tot,last,L,len1,len2;
char ch1[maxn],ch2[maxn];
void init(){
    len[tot=0]=0; len[++tot]=-1;
    fail[0]=1; s[n=0]=-1; last=0;
    clr(to,0);
}
void add(int c,int p[]){
    s[++n]=c;
    int tmp,cur,now;
    for (cur=last;s[n-len[cur]-1]!=c;cur=fail[cur]);
    if (!to[cur][c]){
        len[++tot]=len[cur]+2; now=tot;
        for (tmp=fail[cur];s[n-len[tmp]-1]!=c;tmp=fail[tmp]);
        fail[now]=to[tmp][c];
        to[cur][c]=now;
    } last=to[cur][c];
    cnt[last]++;
    p[n]=n-len[last]+1;
}
int main(){
    scanf("%s",ch1); L=strlen(ch1);
    rep(i,0,L-1) ch2[L-1-i]=ch1[i];
    init();
    rep(i,0,L-1) add(ch1[i]-'a',p1);
    init();
    rep(i,0,L-1) add(ch2[i]-'a',p2);
    rep(i,0,L-1){
        len1=i-p1[i]+1;
        len2=L-i-p2[L-i]+1;
        ans=max(ans,len1+len2);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted on 2015-11-22 22:04  ctlchild  阅读(851)  评论(0编辑  收藏  举报

导航