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

[BZOJ2565]最长双回文串

时间:2018-03-31 23:08:46      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:oid   struct   地方   for   长度   ini   char   max   枚举   

bzoj

题意

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

sol

显然是枚举\(X\)\(Y\)在那个地方断吧。
那么就需要求出位置\(i\)的最长回文后缀和\(i+1\)的最长回文前缀,然后拼起来就可以了。
回文后缀可以直接回文树求。
回文前缀?
\(reverse\)过来再做一遍即可。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5+5;
struct Palindromic_Tree{
    int last,tot,tr[N][26],fa[N],len[N];
    void init(){fa[0]=fa[1]=1;len[tot=1]=-1;}
    void extend(int c,int n,char *s)
        {
            int v=last;
            while (s[n-len[v]-1]!=s[n]) v=fa[v];
            if (!tr[v][c])
            {
                int u=++tot,k=fa[v];
                len[u]=len[v]+2;
                while (s[n-len[k]-1]!=s[n]) k=fa[k];
                fa[u]=tr[k][c];tr[v][c]=u;
            }
            last=tr[v][c];
        }
}t1,t2;
char s[N];int f[N],g[N];
int main()
{
    scanf("%s",s+1);
    int n=strlen(s+1),ans=0;
    t1.init();t2.init();
    for (int i=1;i<=n;++i) t1.extend(s[i]-'a',i,s),f[i]=t1.len[t1.last];
    reverse(s+1,s+n+1);
    for (int i=1;i<=n;++i) t2.extend(s[i]-'a',i,s),g[n-i+1]=t2.len[t2.last];
    for (int i=1;i<n;++i) ans=max(ans,f[i]+g[i+1]);
    printf("%d\n",ans);return 0;
}

[BZOJ2565]最长双回文串

标签:oid   struct   地方   for   长度   ini   char   max   枚举   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8684529.html

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