广义后缀自动机与后缀树

广义后缀自动机

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

​ 构造的时候有离线和在线的做法,dwj老司机的blog有code,2015年lyy的集训队论文有证明。然而离线的时候复杂度要带一个字符集大小?

​ 建的时候其实和单串后缀自动机差不多,就是注意某个节点如果不满足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];
            }
        }
    }
}

后缀树

​ 其实后缀树和后缀自动机差不多是一个东西?fsf大爷讲课的时候我才大概理解了为啥两者能够相似>_<大概就是Trans是像AC自动机的fail边差不多的东西,都是匹配失败之后就跳去某个最优的合法位置。不过广义SAM似乎有点不太一样?直接把它建出来后,它的parent边就形成了“前缀逆序树”,大概就是把主trie上的字符串全部倒过来然后插到一个压缩trie上吧。

你可能感兴趣的:(广义后缀自动机与后缀树)