後綴自動機學習資料

大部分摘抄,小部分原創。
http://blog.csdn.net/sprintfwater/article/details/11880573 (寫錯了)
http://blog.csdn.net/huyuncong/article/details/7583214#comments
http://blog.sina.com.cn/s/blog_70811e1a01014dkz.html
膜大神,我就寫不出這麼清楚的資料。
不過還是總結一下吧,不然會忘。


一些不重要的話:第一次聽說後綴自動機是傅老師說的。當時還是個弱的不行不行的蒟蒻(現在也是)。那時只聽說過後綴數組,AC自動機都不會寫- -||。就隨便口胡一句:會後綴數組不夠嗎。她說:如果後綴數組夠,要SAM幹嘛。現在想想當時我真是naive啊。(2015前半年)
然後在那之後,學會了AC自動機。傅老師那句話一直記得,所以沒學後綴數組,直接看了clj的2012冬令營的ppt和fhq的blog。看了好久沒看懂。未果。開始懷疑人生了。然後棄了一段時間的坑,學了後綴數組(的模板)。當然後來想了想,他們是太神了,我太弱了,但並不代表我需要懷疑人生。clj寫的真的太抽象了
然後SAM就耽誤到了現在。有想法學實在某校內oj上刷模板題,有這道題,本來週一想學,學着學着困了。不過找到了好的講解。今天正式學會了吧。
我看的第一個的圖,第二個的講解(第二個也有圖,最開始沒看見- -||)


在後綴自動機中,每個結點儲存的信息有:
son[26]:返回該結點對應的子串加上某個字符後生成的合法子串在後綴自動機中所對應的位置(其實就和字母樹一樣),如果該指針不存在,就說明這樣的子串是不存在的(即不是s的子串)
pre:注意這不是返回它的父結點(因爲某個點有可能成爲多個結點的兒子),而是返回上一個可以接收後綴的結點(如果當前結點可以接收新的後綴,那麼pre指向的結點也一定可以接收後綴).
step:返回的是從根結點走到該結點,最多需要多少步.

後綴自動機的幾個性質:
①從root到任意結點p的每條路徑上的字符組成的字符串,都是當前串t的子串.
②因爲滿足性質一,所以如果當前結點p是可以接收新後綴的結點,那麼從root到任意結點p的每條路徑上的字符組成的字符串,都是必定是當前串t的後綴.
③如果結點p可以接收新的後綴,那麼p的pre指向的結點也可以接收後綴,反過來就不行.
下面的敘述中,將直接應用這兩個性質.

節點分爲可接受狀態節點和非可接受狀態節點。可接受狀態就是說根節點到該節點組成了上一狀態的後綴,即它在添加你現在要add的字符,它還是後綴。

添加字符x:
np:新加入的節點編號。
p:上一個新增節點按照pre走的節點。
q:p的x兒子。

當前建立的後綴自動機是對應字符串t的,現在要插入字符x,把t的後綴自動機變成tx的後綴自動機.
我們的做法是:
假設當前跳到p結點,如果p沒有x兒子,那麼它一定可以接收新來的字符,然後就把p的x兒子賦值爲np.
然後,就要處理有x兒子的結點了,假設p的x兒子是q.只有2種情況:
①step[q]=step[p]+1.
因爲我們要後綴自動機的結點儘量少,所以要儘量共用一些信息.這是對應的圖:
這時,p點是滿足性質②的.這時,如果可以把np直接接到p後面,就可以省下很多空間了,但是因爲q點的存在, np不能直接接到p後面,否則p-q的信息就丟失了.那麼能不能把q當成np呢?就是說q可不可以像np那樣,作爲t的”最後一個字符”,來接收新的後綴呢?答案是肯定的.但p可以接收新的後綴,q就不一定能接收新的後綴,這樣做會不會有問題?
這裏寫圖片描述
本來,這樣的做法是不行的(這是情況②要解決的問題),但step[q]=step[p]+1,保證了:q原本是從p的路徑上來的,而且p和q之間不會夾雜其它字符.雖然q本來不一定可以接收新的後綴,但p可以接收後綴x,如果當前經過p來到q,就可以視爲是在t的某個後綴後面插入了x(現在q就是那個x),並且在下一次插入的時候,q也可以接收後綴(因爲它現在可以被視爲x的結點了),所以就把np的pre指向q.
這裏寫圖片描述
②step[q]>step[p]+1
這和上一種情況一樣,也面臨着q點是否可以當成x結點的問題.在上一種情況的描述中,我們可以知道, step[q]=step[p]+1可以保證q原本是從p的路徑上來的,而且p和q之間不會夾雜其它字符,所以可以直接把q結點當成x結點.那麼反過來, step[q]>step[p]+1,就說明p和q之間有可能會夾雜其它字符,這就不能保證把q當成x結點以後,到q的路徑都是tx的後綴了,於是我們不能採取和前一種情況一樣的做法.但是,我們可以模仿前一種情況的做法.
上面的做法合法,是因爲step[q]=step[p]+1,那麼如果新建一個結點nq來代替q,同時保證step[nq]=step[p]+1就相當於第一種情況了,這時,只要把q的son邊和pre邊都copy到nq上即可.但是別忘了把nq的pre改爲p,再把q和np的pre都改爲nq.
因爲現在nq代替了q,所以np的pre是nq.由性質③可知nq的pre只能是p.同樣的,q和nq也滿足性質③,所以q的pre只能是nq.
最後,還要再按p的pre指針往上跳,把son[x]=q的p結點改爲son[x]=nq(因爲nq代替了q).
這裏寫圖片描述

這裏寫圖片描述

這裏寫圖片描述

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