[BZOJ2565]最长双回文串(manacher)

题目描述

传送门

题解

这道题实际上是求不重叠且相邻的两个回文串拼在一起的最长长度。
将字符中间都插入#了之后问题转化为对于每一个#求它左边和右边回文串能覆盖到它的最远的回文中心。
这个满足单调性,求出以每一个点为对称中心的最长回文串了之后扫两遍就可以了。

代码

#include
#include
#include
using namespace std;
#define N 500005

char a[N],s[N];
int p[N],l[N],r[N],n,la,mx,id,now,ans;

int main()
{
    gets(a);la=strlen(a);s[0]='*';
    for (int i=0;i'#',s[++n]=a[i];
    s[++n]='#';
    for (int i=1;i<=n;++i)
    {
        if (mx>i) p[i]=min(p[2*id-i],mx-i);
        else p[i]=1;
        while (s[i-p[i]]==s[i+p[i]]) ++p[i];
        if (i+p[i]>mx)
        {
            mx=i+p[i];
            id=i;
        }
    }
    now=1;
    for (int i=1;i<=n;++i)
        if (s[i]=='#')
        {
            while (now+p[now]for (int i=n;i>=1;--i)
        if (s[i]=='#')
        {
            while (now-p[now]>i) --now;
            r[i]=now-i;
        }
    for (int i=1;i<=n;++i) ans=max(ans,l[i]+r[i]);
    printf("%d\n",ans);
}


你可能感兴趣的:(题解,manacher)