廣義字尾自動機(廣義SAM)

2022-09-17 00:36:09 字數 1795 閱讀 4871

參考部落格:【學習筆記】字串—廣義字尾自動機

廣義字尾自動機適用於多串的子串問題。它的dfa可以識別多串中的任意乙個子串。同時也有類似 sam 的一些性質。

模板提交處

根據參考部落格所說,有好幾種 假 寫法。比如:每乙個串的開頭設定 \(lst\) 為 \(1\);多串拼成乙個大串,中間用'#'連線 等等;

正規寫法:

例題:p3346 [zjoi2015]諸神眷顧的幻想鄉

建出所有串的 \(trie\) 樹。然後在 \(trie\) 上 \(bfs\) ,每次將乙個字元加到其 \(trie\) 的 \(fa\) 上。其餘與 sam 同。

\(t_c[cur]:trie\) 上的 \(cur\) 節點的父親節點

\(pos[cur]:trie\) 上的 \(cur\) 節點(所代表子串)在 sam 上的位置

\(int ins(int c, int lst):\) 幾與普通sam同。傳入 \(lst\),傳出 \(np\)

\(code:\)

inline void work() 

}

每乙個串的開頭設定 \(lst\) 為 \(1\)。但是由於一開始可能就存在 \(son[lst][c]\),那就不太妙。因此需要加兩個特判:

特判一

if (son[lst][c] && len[son[lst][c]] == len[lst] + 1)	return son[lst][c];
如果有乙個完美的節點 \(q\),那麼我們直接將 \(lst\) 設定為這個點返回即可。

特判二

//...

//if (len[q] == len[p] + 1) return ...

if (p == lst) flag = true;

//int nq = ++tot; len[nq]...

如果存在乙個不那麼完美的節點 \(q\),那麼我們可以新建乙個節點 \(nq\),然後...(同sam)。這樣我們就和普通 sam 合併一下,在最後判斷一下,如果是這種情況,就直接返回 \(nq\) 即可。可以證明的是,此時建立的 \(p\) 節點是乙個「空點」,因為 \(len[p] = len[lst] + 1, minlen[p] = len[nq] + 1 = len[lst] + 2\)。

**

inline int ins(int c, int lst)
在建立廣義sam的同時,還可以維護每個串的 \(endpos\) 集合,應用 \(len\) 的性質等等。具體見下方。

直接建廣義sam,在dfa上跑即可。

建廣義sam,\(ans = \sum\)

在加入(\(ins\))時,對於表示當前串的節點的\(siz\) 賦值為 1。(注意特判的地方,如果找到了個「完美的替身」,那麼讓替身的 \(siz\) 為1;如果確實要讓nq代替np,那麼將np的siz的那個1轉移給nq)然後再按照類似普通sam的做法搞出 \(endpos\) 集合。(搞\(firstpos\)後線段樹合併)

sp1812 lcs2 - longest common substring ii

建立多串的廣義sam,同時維護每個串的 \(endpos\) 集合(大小)。最後檢查每個節點是否「被所有節點共同擁有」。如果有這樣的節點,那麼可以用這個節點的 \(len\) 更新答案。

調到心態**,暫時放棄。

記錄在這裡:my record

inline int ins(int c, int lst)
continued...

P6139 模板 廣義字尾自動機 廣義 SAM

求n nn個串的不同子串個數 如何在sam samsa m中插入多個字串。可以我們可以通過更改las tlast last 為之前的節點來做,如果插入乙個之前插入過的節點就按照之前sam samsa m的方法特判就好了。include include include define ll long l...

廣義字尾自動機小結

字尾自動機功能很強大,但碰到多串問題就掛。廣義字尾自動機支援多串操作。思想是在每次插入乙個串後,把las設為1即可,其它操作在parent樹上進行表演。bzoj 3277 includeusing namespace std typedef long long ll const int n 3e5 ...

字尾自動機SAM

原理詳細的可以看史上最通俗的字尾自動機詳解 想看懂還是要花很久。實現 include include using namespace std const int maxn 2000010 struct node nodes maxn int las 1 tot 1 char st maxn void...