大部分摘抄,小部分原創。
(寫錯了)
膜大神,我就寫不出這麼清楚的資料。
不過還是總結一下吧,不然會忘。
一些不重要的話:第一次聽說字尾自動機是傅老師說的。當時還是個弱的不行不行的蒟蒻(現在也是)。那時只聽說過字尾陣列,ac自動機都不會寫- -||。就隨便口胡一句:會字尾陣列不夠嗎。她說:如果字尾陣列夠,要sam幹嘛。現在想想當時我真是*****啊。(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.
這和上一種情況一樣,也面臨著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).
字尾自動機學習
今天終於把這週的坑填了,同樣看了很多部落格,這裡就不詳細總結了,就簡單整理一下了。應用 1 存在性查詢 給定文字t,詢問格式如下 給定字串p,問p是否是t的子串。直接按著路徑走,看是否存在即可 2 不同的子串個數 對於每乙個節點即為 len i len fa i 加和即可 3 不同子串的總長 這裡我...
字尾自動機
基礎知識 step i 表示的是字串i在原字串中的位置。pareint i 表示root到parent i 的子串是root到i的最長字尾。字尾自動機遍歷可以得到原字串的所有子串。特殊技巧 一 字尾自動機的不同子串數有兩種求法 1.ans step i step parent i 1 i cnt 2...
字尾自動機
常用於處理字串問題,可以高效解決許多字串問題。有點像將乙個字串的所有字尾都建在乙個ac自動機上,但不同的是字尾自動機的節點數最多為2 n,因為它只記錄需要記錄的點,一些沒有記錄東西的點可以視為與下面有價值的節點並在一起,這樣大大降低了時間複雜度和空間複雜度。對於每乙個節點記錄它的後面加上每個字元後字...