bzoj 2565: 最长双回文串 manachar

来源:互联网 发布:淘宝店解封后有影响吗 编辑:程序博客网 时间:2024/06/05 18:51

题意

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

分析

直接用manachar求出f[i]表示以i为结尾的最长回文串,g[i]表示以i为开头的最长回文串,然后扫一遍即可。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;const int N=200005;int n,w[N],f[N],a[N],g[N],len[N];char s[N];void manachar(){    for (int i=1;i<=n;i++) a[i*2]=s[i]-'a',a[i*2-1]=30;    a[n*2+1]=30;    int mx=0,pos=0;    for (int i=1;i<=n*2+1;i++)    {        if (mx>=i) len[i]=min(mx-i+1,len[pos*2-i]);        else len[i]=1;        while (i-len[i]>0&&i+len[i]<=n*2+1&&a[i-len[i]]==a[i+len[i]])        {            len[i]++;            if (i+len[i]-1>mx) w[i+len[i]-1]=len[i]*2-1;        }        if (i+len[i]-1>mx) mx=i+len[i]-1,pos=i;    }}int main(){    scanf("%s",s+1);    n=strlen(s+1);    manachar();    for (int i=1;i<=n;i++) f[i]=w[i*2+1]/2;    for (int i=1;i<=n/2;i++) swap(s[i],s[n-i+1]);    manachar();    for (int i=1;i<=n;i++) g[n-i+1]=w[i*2+1]/2;    int ans=0;    for (int i=1;i<n;i++) ans=max(ans,f[i]+g[i+1]);    printf("%d",ans);    return 0;}
原创粉丝点击