最长双回文串

题目大意:

输入长度为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
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10014582.html