广义后缀自动机与后缀树

来源:互联网 发布:apt get yum rpm 编辑:程序博客网 时间:2024/05/16 10:37

广义后缀自动机

​ 就是给一堆字符串,把这些字符串插进一个trie之后,能够接收从某个trie节点走到叶子节点(也就是原来任意一个字符串的后缀)的字符串的自动机。

​ 构造的时候有离线和在线的做法,dwj老司机的blog有code,2015年lyy的集训队论文有证明。
 广义后缀自动机的转移数是O(|Σ||T|)的,其中Σ为字符集,|T|为trie的大小。离线建SAM(也就是按串的长度从小到大插入)可以得到这个下界,而在线建的时间复杂度是O(|Σ||T|+G(T)),其中G(T)T这棵trie中所有叶子节点的深度和。

​ 在线建的时候其实和单串后缀自动机差不多,就是注意某个节点如果不满足len的性质的时候要再新建节点搞搞信息,和单串SAM建立的某个时候的分类讨论基本上是一样的,而离线建的时候是完全一样的代码。

​ 我的代码:(在线)

inline void add(char c) {    int np = go[ed][c];    if (np) {        if (len[np] == len[ed] + 1)            ed = np;        else {            int r = ++ tot;            len[r] = len[ed] + 1;            fa[r] = fa[np] , fa[np] = r;            go[r] = go[np];            int p = ed;            while (go[p][c] == np)                go[p][c] = r , p = fa[p];            ed = r;        }    } else {        int p = ed;        np = ed = ++ tot;        len[np] = len[p] + 1;        while (!go[p][c])            go[p][c] = np , p = fa[p];        if (!p)            fa[np] = 1;        else {            int q = go[p][c];            if (len[q] == len[p] + 1)                fa[np] = q;            else {                int r = ++ tot;                len[r] = len[p] + 1;                fa[r] = fa[q] , fa[q] = fa[np] = r;                go[r] = go[q];                while (go[p][c] == q)                    go[p][c] = r , p = fa[p];            }        }    }}

广义后缀树

​ 直接把广义后缀自动机建出来后,它的parent边就形成了“前缀的逆序树”,也就是说把主trie上的字符串全部倒过来然后插到一个压缩trie上。

1 0
原创粉丝点击