bzoj千题计划305:bzoj2565: 最长双回文串(回文自动机)

https://www.lydsy.com/JudgeOnline/problem.php?id=2565

 

正着构造回文自动机

倒过来再构造一个回文自动机

分别求出以位置i开始的和结尾的最长回文串

 

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;

#define N 100001

char ss[N];
int s[N];

int L1[N],L2[N];

struct TREE
{
    int tot,last;
    int len[N],tr[N][26],fail[N];
    int p,c,np,t;
    
    int n;
    
    void clear()
    {
        tot=1; last=0;
        memset(tr[0],0,sizeof(tr[0]));
        memset(tr[1],0,sizeof(tr[1]));
        fail[0]=1; fail[1]=0;
        len[0]=0; len[1]=-1;
        s[0]=-1; n=0;
    }
    
    int newnode(int f)
    {
        tot++;
        memset(tr[tot],0,sizeof(tr[tot]));
        fail[tot]=0;
        len[tot]=len[f]+2;
        return tot;
    }
    
    int extend(int c)
    {
        s[++n]=c;
        p=last;
        while(s[n-1-len[p]]!=c) p=fail[p];
        if(!tr[p][c])
        {
            np=newnode(p);
            t=fail[p];
            while(s[n-1-len[t]]!=c) t=fail[t];
            fail[np]=tr[t][c];
            tr[p][c]=np;
        }
        else np=tr[p][c];
        return len[last=np];
    }
    
}tree;

int main()
{
    scanf("%s",ss+1);
    int n=strlen(ss+1);
    tree.clear();
    for(int i=1;i<=n;++i) 
        L1[i]=tree.extend(ss[i]-'a');
    tree.clear();
    for(int i=n;i;--i) 
        L2[i]=tree.extend(ss[i]-'a');
    int ans=0;
    for(int i=1;i<n;++i) ans=max(ans,L1[i]+L2[i+1]);
    printf("%d",ans); 
} 

 

posted @ 2018-04-01 17:43  TRTTG  阅读(287)  评论(0编辑  收藏  举报