廣義字尾自動機與字尾樹
阿新 • • 發佈:2019-02-11
廣義字尾自動機
就是給一堆字串,把這些字串插進一個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];
}
}
}
}
廣義字尾樹
直接把廣義字尾自動機建出來後,它的parent邊就形成了“字首的逆序樹”,也就是說把主trie上的字串全部倒過來然後插到一個壓縮trie上。