Luogu P4287 [SHOI2011]双倍回文PAM

多维护一个转移 (tra[p]),表示 (leq frac{len[p]}{2}) 的后缀位于的状态。

最后检查一下是否有 (len[tra[p]]=len[p]/2 && len[tra[p]]\%2==0)

#include<iostream>
#include<cstdio>
#include<cstring>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
  register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
  do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=100010;
int n,tot,lst,ans;
int fa[N],c[N][26],len[N],cnt[N],sz[N],tra[N];
char s[N];
inline int jmp(int p,int i) 
  {while(s[i-len[p]-1]!=s[i]) p=fa[p]; return p;}
inline void add(int ch,int i) {
  R p=jmp(lst,i); if(!c[p][ch]) {
    R np=++tot; len[np]=len[p]+2;
    R t=jmp(fa[p],i);
    fa[np]=c[t][ch],c[p][ch]=np;
    if(len[np]<=2) tra[np]=fa[np];
    else {
      t=tra[p];
      while(s[i-len[t]-1]!=s[i]||(len[t]+2)*2>len[np]) t=fa[t];
      tra[np]=c[t][ch]; 
    }
  } lst=c[p][ch];
}
inline void main() {
  n=g(),scanf("%s",s+1);
  s[0]='#',len[fa[fa[1]=0]=tot=1]=-1;
  for(R i=1;i<=n;++i) add(s[i]-'a',i);
  for(R i=2;i<=tot;++i)
    if(len[tra[i]]*2==len[i]&&!(len[tra[i]]&1)) 
      ans=max(ans,len[i]);
  printf("%d
",ans);
}
} signed main() {Luitaryi::main(); return 0;}

2020.01.16

原文地址:https://www.cnblogs.com/Jackpei/p/12202915.html