洛谷P4287 [SHOI2011]双倍回文(回文自动机)

传送门

 

听说有大佬用manacher$O(n)$过此题……太强啦……

说一下PAM的做法吧。(看了题解之后发现)蛮简单的

我们肯定要先建出回文自动机的

然后如果是枚举每一个节点暴跳fail指针肯定得T

那么我们对于每一个节点记录一个$trans[i]$,表示小于等于它长度一半的节点

这个可以在建自动机的时候顺便求出来,具体看代码

然后对每一个节点判断长度是否模4为0且$trans[i]$的长度是它的一半就好了

 1 //minamoto
 2 #include<cstdio>
 3 #include<cstring>
 4 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 5 const int N=500005;
 6 int fail[N],ch[N][26],cnt[N],len[N],trans[N];
 7 int n,m,tot,last,p,q,ans;
 8 char s[N];
 9 inline int newnode(int x){
10     len[++tot]=x;return tot;
11 }
12 inline int getfail(int x,int n){
13     while(s[n-1-len[x]]!=s[n]) x=fail[x];return x;
14 }
15 void build(){
16     for(int i=1;s[i];++i){
17         int x=s[i]-'a';
18         p=getfail(last,i);
19         if(!ch[p][x]){
20             q=newnode(len[p]+2);
21             fail[q]=ch[getfail(fail[p],i)][x];
22             ch[p][x]=q;
23             if(len[q]<=2) trans[q]=fail[q];
24             else{
25                 int tmp=trans[p];
26                 while(s[i-1-len[tmp]]!=s[i]||(len[tmp]+2)*2>len[q]) tmp=fail[tmp];
27                 trans[q]=ch[tmp][x];
28             }
29         }
30         cnt[last=ch[p][x]]++;
31     }
32 }
33 int main(){
34 //    freopen("testdata.in","r",stdin);
35     scanf("%d",&n);
36     scanf("%s",s+1);
37     s[0]=-1,fail[0]=1,last=0;
38     len[0]=0,len[1]=-1,tot=1;
39     build();
40     for(int i=tot;i>=2;--i) cnt[fail[i]]+=cnt[i];
41     for(int i=2;i<=tot;++i)
42     if((len[trans[i]]<<1)==len[i]&&len[i]%4==0) cmax(ans,len[i]);
43     printf("%d\n",ans);
44     return 0;
45 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9629708.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值