[算法模版]回文树

时间:2020-01-18 20:46:55   收藏:0   阅读:115

回文树

本文全文引自yijan,特此鸣谢。

回文树,也就是回文自动机,PAM(Palindrome automaton) 是一个处理回文串的有力工具。然而这个东西比SAM简单多了。。

(它可能比 manacher 要强得多?)

回文自动机有两个根,也就是说其实是有两个树的,一个存储长度为奇数的回文串一个存储长度为偶数的回文串。

回文自动机上的每一个节点表示一个本质不同的回文串。也就是说回文自动机上的节点个数就是本质不同的回文串个数。

由于回文树的构造方法类似后缀自动机采用增量法,有一个重要的结论:

贴个板子

struct PAM {
    int next[maxn][ALP] , fail[maxn] , cnt[maxn] , num[maxn] , len[maxn] , s[maxn];
    int last, n, p;
    struct edge {
        int v, nxt;
    } e[maxn];
    int ecnt, head[maxn];
    bool vis[maxn];

    void adde(int u, int v) {
        e[++ecnt].v = v;
        e[ecnt].nxt = head[u];
        head[u] = ecnt;
    }

    int newnode(int l) {
        for (int i = 0; i < ALP; i++)
            next[p][i] = 0;
        cnt[p] = num[p] = 0;
        len[p] = l;
        return p++;
    }

    void init() {
        vis[0] = vis[1] = 0;
        ecnt = 0;
        for (int i = 0; i <= p; ++i) head[i] = 0;
        p = 0;
        newnode(0);
        newnode(-1);
        last = 0;
        n = 0;
        s[n] = -1;
        fail[0] = 1;
    }

    int get_fail(int x) {
        while (s[n - len[x] - 1] != s[n]) x = fail[x];
        return x;
    }

    void add(int c) {
        c = c - 'a';
        s[++n] = c;
        int cur = get_fail(last);
        if (!next[cur][c]) {
            int now = newnode(len[cur] + 2);
            fail[now] = next[get_fail(fail[cur])][c];
            next[cur][c] = now;
            num[now] = num[fail[now]] + 1;
        }
        last = next[cur][c];
        cnt[last]++;
    }

    void count() {
        for (int i = p - 1; i >= 0; i--)
            cnt[fail[i]] += cnt[i];
    }

    void build() {
        for (int i = 0; i <= p - 1; ++i)
            adde(fail[i], i);
    }

}pam;  

技术分享图片

原文:https://www.cnblogs.com/GavinZheng/p/12210034.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!