回文自动机(PAM)

https://www.luogu.com.cn/problem/P5496

https://www.luogu.com.cn/blog/luotianze/solution-p5496

#include <bits/stdc++.h> using namespace std; const int N=(int)(2e6+5); char s[N]; int n,fail[N],len[N],ans[N],ch[26][N],cur,tot=1; int get_fail(int x,int i) { while(i-len[x]-1<0||s[i-len[x]-1]!=s[i]) x=fail[x]; // x-len[x]-1 <0 : 跳到偶根 return x; } signed main() { scanf("%s",s); n=strlen(s); fail[0]=1; len[1]=-1; int las=0; for(int i=0;i<n;i++) { if(i>=1) s[i]=(s[i]-97+las)%26+97; int p=get_fail(cur,i),c=s[i]-'a'; if(!ch[c][p]) { ++tot; fail[tot]=ch[c][get_fail(fail[p],i)]; ch[c][p]=tot; len[tot]=len[p]+2; ans[tot]=ans[fail[tot]]+1; } cur=ch[c][p]; printf("%d ",las=ans[cur]); } }

几点做题时遇到的性质

  1. 本质相同的回文子串在回文树上的对应节点相同(1 个 1 个匹配显然)

  2. cur 维护的是 [1,i1] 的最长后缀回文子串在后缀树上对应的节点。考虑当前是不是要增加 si 这个字符(在自动机的构建中大多都是以增量法来构建的),那么显然我们要找到一个最小的 j 满足 [j,i] 是回文串,显然 [j+1,i1] 是回文串,所以我们跳 cur 的 fail 指针,考虑能否增量这一个新字符。考虑之后 p 对应的就是 [q,i1] 最小的 q 满足 2 端都能增量新字符的 s[q,i1] 在后缀树上的节点。那么考虑一个回文串在回文树上的匹配,是不是假如本质相同了,那么到达的也应该也一样啊?(类 Trie)也就是要看看当前是否出现过。后面的 fail 的构造就类 AC 自动机了。需要注意的是,虽然当前都是在以 i 为结尾的构造,但是本质相同的话的构造与当前的构造一定是一样的。


__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16551302.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示