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

最长双回文串

时间:2018-11-25 11:42:23      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:scanf   main   void   oid   turn   回文串   pac   ==   font   

题目大意:

输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分XY,(|X|,|Y|≥1)且XY都是回文串。

题解:
若X,Y都是回文串且相邻,则共用一个’#‘。

可以对于每个‘#’找出其左边界和右边界。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100050
char s0[N],s[2*N];
int l0,len;
int p[2*N],l[2*N],r[2*N];
void manacher()
{
    int mid=0,mx=0;
    for(int i=1;i<=len;i++)
    {
        if(i<=mx)p[i]=min(p[2*mid-i],mx-i+1);
        else p[i]=1;
        while(s[i+p[i]]==s[i-p[i]])p[i]++;
        l[i+p[i]-1]=max(p[i]-1,l[i+p[i]-1]);
        r[i-p[i]+1]=max(p[i]-1,r[i-p[i]+1]);
        if(i+p[i]-1>mx)
        {
            mid=i;
            mx=i+p[i]-1;
        }
    }
}
int main()
{
    scanf("%s",s0+1);
    l0 = strlen(s0+1);
    s[0]=!;
    for(int i=1;i<=l0;i++)
    {
        s[++len]=#;
        s[++len]=s0[i];
    }
    s[++len]=#;
    s[++len]=@;
    manacher();
    for(int i=3;i<=len;i+=2)
        r[i]=max(r[i],r[i-2]-2);
    for(int i=len;i>=1;i-=2)
        l[i]=max(l[i],l[i+2]+2);
    int ans = 0;
    for(int i=1;i<=len;i+=2)
        ans=max(ans,r[i]+l[i]);
    printf("%d\n",ans);
    return 0;
}

 

最长双回文串

标签:scanf   main   void   oid   turn   回文串   pac   ==   font   

原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10014582.html

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