《淺談壓縮後綴自動機》 - 學習筆記

以前對後綴數據結構的理解不夠深刻,希望讀完這篇論文之後可以有較爲透徹的認識。

3 OI 中的傳統後綴數據結構

3.1 後綴字典樹

把所有後綴拎出來建字典樹,然後把後綴對應的點標記爲灰色。

3.2 後綴自動機

DFA 的最小化的概念:(我並沒有查找資料所以只是個人理解)如果兩個點連向的點對應等價,那麼這兩個點也等價,可以合併到一起。

比如上圖中可以把 aab,abaab,baab 合併,然後把 aa,abaa,baa 合併,等等。

定義 3.2 :把後綴字典樹上 \(Right\) 集合相同的節點合併,得到的 DFA 稱爲後綴自動機。

把除了開始狀態外,出度不爲 1 的點標記爲灰色(注意兩種標灰色的方法是不一樣的)。

顯然沿着後綴自動機的邊 dfs 一遍可以得到原來的後綴字典樹。

注意在定義中沒有提到最小化的概念。事實上合併 \(Right\) 集合相同的點和最小化是類似的,但不完全相同,比如下面這個例子

可以發現,唯一的差別就是是否會把 \(Right\) 集合的對稱差恰好是 \(\{|S|\}\) 的點合併,這是因爲 \(|S|\) 是否出現在 \(Right\) 集合中對出邊沒有影響。

所以如果在最小化時強制要求灰色和白色的點不能合併,那麼得到的結果就一樣了。

後綴自動機有用的本質原因:兩個 \(Right\) 集合要麼不交,要麼互相包含,所以組成了一個不超過 \(n\) 個葉子的樹形結構,所以節點數在 \(O(|S|)\) 級別。

3.3 後綴樹

後綴字典樹的葉子個數只有至多 \(|S|\) 個,對它們建立虛樹就會得到後綴樹。

顯然這就是把所有出度爲 1 的節點縮起來。稱這個過程爲對後綴字典樹的收縮。

注意有一些灰色點(即對應到一個後綴的點)也被縮起來了。如果是對所有代表原串後綴的點(而非僅僅是葉子)建虛樹,得到的叫做完整後綴樹。

4 壓縮後綴自動機

4.1 定義

上面分別對後綴字典樹進行了收縮和最小化操作,那麼如果兩個都做(先後順序不影響),就稱得到的結果爲壓縮後綴自動機。

或者對於完整後綴樹做最小化,就得到完整壓縮後綴自動機。

也就是把 \(Right\) 集合包含 \(|S|\) 的點留下來。

4.2 構造方式

顯然最小化比較難做,所以考慮對後綴自動機進行收縮。

這顯然可以隨便做。不過怎樣維護每條邊上的串在原串中是哪一段呢?可以根據 \(Right\) 集合和這條邊的長度得到。

完整壓縮後綴自動機也類似。

4.3 性質與應用

性質 4.3.1 :各個節點在壓縮後綴自動機上所有入邊上的字符串是其中最長者的後綴。

性質 4.3.2 :壓縮後綴自動機是後綴樹最小化的結果。在壓縮後綴自動機上 dfs ,可以還原出後綴樹(不是後綴字典樹!)。

定理 4.3 :令 \(L_i\) 表示壓縮後綴自動機第 \(i\) 個節點的所有入邊中最長邊的長度,則 \(\sum L_i=O(|S|)\)

這是因爲後綴自動機中的每條邊最多貢獻一次。

這與性質 4.3.1 放在一起非常強大,因爲現在可以暴力處理每條邊上的字符串了。(不過好像除非是題目要求,不然也沒有太大用處?)

5 對稱壓縮後綴自動機

5.1 定義

對於同一個節點可以接收的字符串集合 \(\{T_i\}\) ,令其中最長的是 \(T_{Max}\) ,那麼其他串都是 \(T_{Max}\) 的後綴(我也就是這麼理解性質 4.3.1 的,不知道另一種方法是怎麼樣)。

並且考慮 \(Right\) 集合的定義,有

\[\forall T\in \{T_i\},LeftContext(T)=T_{Max} \]

所以也可以用 \(T_{Max}\) 來描述後綴自動機上的節點。

也就有另一種理解後綴自動機的方式:它保留了後綴字典樹中 \(LeftContext(T)=T\) 的節點。

而出度爲 1 ,且對應 \(Right\) 集合不包含 \(|S|\) 的節點具有唯一的出邊,且不代表原串的一個後綴,所以它滿足 \(RightContext(T)\ne T\) 。這樣的點在構建完整壓縮後綴自動機的時候被收縮了。

所以完整壓縮後綴自動機的每一個點對應的 \(T\) 滿足 \(Context(T)=T\) 。可以用這樣的串來描述一個節點。

注意到 \(Context(T)=T\) 的子串 \(T\)\(S\) 的反串中的 \(T'\) 是一一對應的,嘗試對正串和反串分別建立完整壓縮後綴自動機,合併對應的節點。

同時對字符串的正反串建立完整壓縮後綴自動機,將對應的節點合併,並同時保留兩組轉移邊,稱得到的結果爲對稱壓縮後綴自動機。

綠色是正串的,表示往後添加字符;紅色是反串的,表示往前添加字符(看着有點暈)。

5.2 構造方式

分別構造,然後合併。爲了找到對應節點可以使用字符串哈希。

5.3 性質與應用

如果只有操作 1 那就直接普通後綴自動機即可。有操作 2 似乎也可以?

建出對稱壓縮後綴自動機,用 \(Context(T)\) 對應的節點表示 \(T\) ,並維護 \(T\)\(Context(T)\) 中的出現位置(顯然是唯一的,不然可以一路往左推)。

然後在對稱壓縮後綴自動機裏面跳即可。

先考慮怎麼判斷一個串是否是必勝態。注意到對於 \(LeftContext(T)\ne T,RightContext(T)\ne T\) 的子串 \(T\) ,它的下一步是確定的,所以只需要考慮至少滿足一個的串即可。由定理 4.3 ,這樣的串只有 \(O(|S|)\) 個(也就是正反 SAM 的節點對應的最長串),可以暴力 DP 。

字典序只需要隨便 dfs 一下即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章