廣義後綴自動機與後綴樹

廣義後綴自動機

​ 就是給一堆字符串,把這些字符串插進一個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上。

發佈了135 篇原創文章 · 獲贊 6 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章