ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。
输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分XY,(|X|,|Y|≥1)且XY都是回文串。

Input

一行由小写英文字母组成的字符串S

Output

一行一个整数,表示最长双回文子串的长度。
 正反各运行一次manacher,同时求出以某个位置为左/右边界的最长回文串长度,最后扫描一次每个分界点取最大值。
#include<cstdio>
#include<cstring>
char s[200010],s1[100010];
int p[200010],p2[200010];
int rx[200010];
int lx[200010];
inline int min(int a,int b){return a<b?a:b;}
inline int maxs(int&a,int b){if(a<b)a=b;}
int main(){
    scanf("%s",s1);
    int l=strlen(s1);
    for(int i=0;i<l;i++)s[i+i+2]=s1[i];
    l+=l;
    s[0]=1;
    s[l+1]=2;
    int mx=0,id=0;
    for(int i=2;i<=l;i++){
        if(i<mx)p[i]=min(p[(id<<1)-i],mx-i);
        else p[i]=1;
        maxs(rx[i],1);
        while(s[i+p[i]]==s[i-p[i]]){
            if(i+p[i]<=l)maxs(rx[i+p[i]],p[i]+1);
            ++p[i];
        }
        if(i+p[i]>mx){
            mx=i+p[i];
            id=i;
        }
    }
    mx=id=l+1;
    for(int i=l;i>=2;i--){
        if(i>mx)p2[i]=min(p2[(id<<1)-i],i-mx);
        else p2[i]=1;
        maxs(lx[i],1);
        while(s[i-p2[i]]==s[i+p2[i]]){
            if(i-p2[i]>=2)maxs(lx[i-p2[i]],p2[i]+1);
            ++p2[i];
        }
        if(i-p2[i]<mx){
            mx=i-p2[i];
            id=i;
        }
    }
    int ans=0;
    for(int i=3;i<l;i+=2)maxs(ans,lx[i+1]+rx[i-1]);
    printf("%d",ans);
    return 0;
}

 

posted on 2016-02-23 21:57  nul  阅读(259)  评论(0编辑  收藏  举报