码迷,mamicode.com
首页 > 其他好文 > 详细

【BZOJ】2565: 最长双回文串

时间:2017-12-10 20:15:37      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:zoj   string   左右   题意   imp   print   分享图片   const   main   

【题意】给定小写字母字符串s,求最长的 [ 可以分成左右两个回文串的 ] 子串,n<=10^5。

【算法】回文树

【题解】对于每个字符x,处理出以x结尾的最长回文串,以x开头的最长回文串,然后枚举中间点求解。

只须正反用两次回文树就可以处理完毕。

技术分享图片
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100010;
int length,sz,nownode,n,fail[maxn],len[maxn],ch[maxn][30],a[maxn],b[maxn];
char s[maxn];
int getfail(int x){while(s[length-len[x]-1]!=s[length])x=fail[x];return x;}
void insert(int a[]){
    int c=s[++length]-a;
    int x=getfail(nownode);
    while(!ch[x][c]){
        len[++sz]=len[x]+2;
        fail[sz]=ch[getfail(fail[x])][c];
        ch[x][c]=sz;
    }
    nownode=ch[x][c];
    a[length]=len[nownode];
}
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    len[0]=0;fail[0]=1;
    len[1]=-1;fail[1]=1;
    length=0;
    sz=1;//important!
    for(int i=1;i<=n;i++)insert(a);
    len[0]=0;fail[0]=1;
    len[1]=-1;fail[1]=1;
    length=0;
    sz=1;//
    for(int i=1;i<=n/2;i++)swap(s[i],s[n-i+1]);
    for(int i=1;i<=n;i++)insert(b);
    int ans=0;
    for(int i=0;i<=n;i++)ans=max(ans,a[i]+b[n-i]);
    printf("%d",ans);
    return 0;
}
View Code

 

【BZOJ】2565: 最长双回文串

标签:zoj   string   左右   题意   imp   print   分享图片   const   main   

原文地址:http://www.cnblogs.com/onioncyc/p/8017785.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!