後綴自動機學習筆記

學了半天,終於大概搞懂後綴自動機是個什麼鬼東西了

這裏做一個筆記(以免以後忘掉)

首先我們要注意一個問題:後綴自動機與trie樹的形式與構造思想差距均是相對大的,所以不能完全用trie樹的角度來理解後綴自動機!!!

然後我們進入正題

基本每個博客都會給出這樣一個定義:後綴自動機是一個可以接受這個字符串所有後綴的確定性有限狀態自動機

但是這個定義對於初學者而言可以說幾乎毫無用處!!!

所以我們換一個角度,直接從後綴自動機的結構形式講起

後綴自動機,顧名思義,它的作用是識別這個字符串的所有後綴。

所以在構造的時候後綴自動機一定與後綴息息相關。

而且我們知道,一個字符串的一個子串一定是某一個後綴的前綴

所以後綴自動機也具有識別子串的作用。

那麼我們舉個例子:

接下來所有例子對應的字符串均爲ababa

那麼首先我們找出它的所有後綴:a,ba,aba,baba,ababa

接下來,我們把這些後綴扔到一棵trie樹上(雖然後綴自動機與trie樹區別不小,但是從trie樹入手更容易理解)

所以我們建成的trie樹長這樣:

發現什麼問題沒?

要命啊,長度僅僅爲5的串建起來已經長這樣了,那要是長度更長空間豈不是會炸飛?

(這個道理很顯然,因爲一個長度爲n的字符串會有n個後綴,而這n個後綴的總長度將是O(n^2)級別的,所以這樣構造的時空複雜度均爲O(n^2))

但是這顯然是無法接受的。

但是我們稍微觀察一下,就會發現:下圖中用綠色線連起來的節點是完全一樣的!所以我們沒有必要存兩遍!

所以我們壓縮一下,就會得到這種東西:

(爲了簡化,這裏只給出了前兩個後綴合併後的結果)

但是,現象已經很明顯了:加入第二個後綴時,並沒有生成新的節點!

這是對空間巨大的優化!

但是請注意,在這裏就已經與trie樹產生本質區別了!可以發現,這並不是一個樹形結構,而是一個圖!

所以後綴自動機是字符串自動機中爲數不多的圖狀結構(雖然我只會兩種字符串自動機)

當然了,如果我們仍然堅持逐個後綴加入的話,那麼時間是無法優化的。

所以接下來就引出了後綴自動機的第一個難點:增量構造法!

我們具體來看一下這個算法的過程。

爲了實現這個算法,我們還要再引入一個指針pre,用來記錄最長後綴的位置,這一點與AC自動機的fail指針很相似

這個算法的實現方式如下:

首先,我們在根節點上加入第一個字符,此時正常加入即可,藍色的線代表pre指針

注意到旁邊標記了一個len,這個先不用管,一會就知道了

然後加入第二個節點

在加入第二個節點時,我們需要不斷向上跳pre指針,跳到的點如果沒有這個兒子(即值爲‘b’的兒子)則直接將對應點的‘b’兒子指向這個節點即可,這也就是根節點向b連邊的原因

(這樣連邊的原因之一是,字符串中任何一個節點都會是一個後綴的起點,那麼爲了從根節點出發能識別所有後綴一定要保證根節點向每個對應節點都有連邊,但是不一定要爲了形成連邊產生新的節點)

然後我們再插入下一個節點

不難發現,如果我們直接構造的話,形成的結構應該如上圖所示

但是很顯然會發現一個問題:根據pre指針的定義,新加入節點的pre指針應當指向上面的'a'而非根節點!

這個問題是如何產生的呢?

我們看到,假設這個串只有aba三個字母,那麼根據後綴自動機可以識別子串,子串'a'出現了兩次,那麼正常來講,在後綴自動機中應該可以成功識別串“a”兩次。

(當然,後綴自動機對子串的識別是基於parent樹實現的,這裏先不做深入討論。)

 

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