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

版权声明:本文为博主原创文章,转载时请标明出处。 https://blog.csdn.net/FarmerJohnOfZS/article/details/81006479

构造方法

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

记录其长度 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;
    }
}

猜你喜欢

转载自blog.csdn.net/FarmerJohnOfZS/article/details/81006479