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

 

解法一:

对原串构建回文自动机

抽离fail树,从根开始dfs

设len[x]表示节点x表示的最长回文子串长度

在fail树上,x到根节点的路径上的点表示的字符串包含了x代表的回文子串的所有回文后缀/前缀

所以若dfs到了x,若len[x]为偶数,标记len[x]*2,如果在x的子树中能找到len为len[x]*2的点,那么len[x]*2*2就可以用来更新答案

 

 
#include<cstdio>
#include<algorithm>
 
using namespace std;
 
#define N 500001
 
char ss[N+1];
int s[N+1];
 
int tot=1,last;
int len[N],fail[N],tr[N][26];
int p,c,np,t;
 
bool ok[N<<1];
int ans;
 
int front[N],to[N],nxt[N],cnt;
 
void add(int u,int v)
{
    to[++cnt]=v; nxt[cnt]=front[u]; front[u]=cnt;
}
 
void extend(int i)
{
    p=last; c=s[i];
    while(s[i-1-len[p]]!=c) p=fail[p];
    if(!tr[p][c])
    {
        np=++tot;
        len[np]=len[p]+2;
        t=fail[p];
        while(s[i-1-len[t]]!=c) t=fail[t];
        fail[np]=tr[t][c];
        add(fail[np],np);
        tr[p][c]=np;
    }
    else np=tr[p][c];
    last=np;
}
 
void dfs(int x)
{
    if(ok[len[x]]) ans=max(ans,len[x]);
    if(!(len[x]&1)) ok[len[x]<<1]=true;
    for(int i=front[x];i;i=nxt[i]) dfs(to[i]);
    if(!(len[x]&1)) ok[len[x]<<1]=false;
}
 
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",ss+1);
    s[0]=-1;
    for(int i=1;i<=n;++i) s[i]=ss[i]-'a';
    fail[0]=1;
    len[1]=-1;
    for(int i=1;i<=n;++i) extend(i);
    dfs(0);
    printf("%d",ans);
}
View Code

相关文章:

  • 2021-10-24
  • 2021-09-29
  • 2022-12-23
  • 2021-08-30
  • 2021-10-06
  • 2021-12-09
  • 2021-07-23
猜你喜欢
  • 2021-07-26
  • 2022-03-03
  • 2021-05-21
  • 2021-05-17
  • 2021-12-23
  • 2021-07-24
  • 2022-12-23
相关资源
相似解决方案