回文自动机(回文树)_处理回文字串的法宝

构造方法

思考如何表示一个回文子串

记录其长度 len 和出现次数 cnt

由于每个子串可以表示成另一个回文串在两边各添加一个字符 c

那么 考虑构造一棵回文树 表示所有出现的回文子串

使用增量法 考虑已经构造了 S 的回文树 现在添加字符c 构造 Sc

我们需要找到以 c 结尾的最长回文子串 设末尾为 cMc

发现 M 为 S 的最长回文后缀 其(最长回文后缀)指针记作fail[S]

如何求得 cMc 的 fail ? 继续在M中重复寻找合法fail即可

由 manacher 正确性可知 点数最多为 O(n)

Code

char s[N];
struct pali{
    int sz,cnt[N];
    int to[N][26],fail[N];
    int len[N],ln,las;
    int st[N];
    int gf(int x){while(st[ln-len[x]-1]!=st[ln])x=fail[x];return(x);}//getfail 即x点最长回文后缀
    void add(int x)
    {
        st[++las]=x;int p=gf(las);//p代表文中M点
        if(!to[p][x]) len[++sz]=len[p]+2,fail[sz]=to[gf(fail[p])][x],to[p][x]=sz;
        ++cnt[las=to[p][x]];//子串出现次数 注意要累加给其包含串 因为此时只计算了最长一个 
    }
    void init()
    {
        len[sz=1]=-1;
        fail[0]=1;
        st[0]=-1;
        las=0;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值