1. 程式人生 > >[置頂]AC自動機-演算法詳解

[置頂]AC自動機-演算法詳解

What's Aho-Corasick automaton?

  一種多模式串匹配演算法,該演算法在1975年產生於貝爾實驗室,是著名的多模式匹配演算法之一。

  簡單的說,KMP用來在一篇文章中匹配一個模式串;但如果有多個模式串,需要在一篇文章中把出現過的模式串都匹配出來,就需要Aho-Corasick automaton演算法了。

My Understanding About Aho-Corasick automaton

    我的理解:Aho-Corasick automaton = Trie + KMP

  在KMP演算法中,匹配單個字元的時候,我們只需要按照文字線性的掃一遍,然後中途失配的時候,next陣列會引導k回溯到正確的位置進行下一步的匹配。

  但是多個模式串的時候要怎麼匹配呢?Trie樹不就是一個多模式的匹配嗎,如果我們將KMP和Trie數結合起來,是不是會有意想不到的效果呢?

  有了這些思考,AC自動機演算法就這樣產生了。

  在AC自動機中,我們首先將每一個模式串插入到Trie樹中去,建立一棵Trie樹,然後構建fail指標,fail指標,顧名思義,就是當匹配失敗的時候,用來引導k回溯的一個插穿在Trie樹的各個節點之間的一些指標,就和KMP演算法中的next陣列是一樣的道理。

  關於fail指標的構建,推薦看一下李翔大神的PPT。

  ppt下載連結:

1.構建Trie樹

  

2.在Trie樹上構建fail指標

  

構建完fail指標後,我們就用文章來對這棵Trie樹進行匹配了。

  匹配過程分兩種情況:

  • 當前字元匹配,表示從當前節點沿著樹邊有一條路徑可以到達目標字元,此時只需沿該路徑走向下一個節點繼續匹配即可,目標字串指標移向下個字元繼續匹配;
  • 當前字元不匹配,則去當前節點fail指標所指向的字元繼續匹配,匹配過程隨著指標指向root結束。重複這2個過程中,直到模式串走到結尾為止。

  對照上圖,看一下模式匹配這個詳細的流程,其中模式串為yasherhs。

  對於i=0,1。Trie中沒有對應的路徑,故不做任何操作;i=2,3,4時,指標p走到左下節點e。

  因為節點e的count資訊為1,所以cnt+1,並且講節點e的count值設定為-1,表示改單詞已經出現過了,防止重複計數,最後temp指向e節點的失敗指標所指向的節點繼續查詢,以此類推,最後temp指向root,退出while迴圈,這個過程中count增加了2,表示找到了2個單詞she和he。

  當i=5時,程式進入第5行,p指向其失敗指標的節點,也就是右邊那個e節點,隨後在第6行指向r節點,r節點的count值為1,從而count+1,迴圈直到temp指向root為止。

  最後i=6,7時,找不到任何匹配,匹配過程結束。

匹配過程總結:

從root節點開始,每次根據讀入的字元沿著自動機向下移動。

當讀入的字元,在分支中不存在時,遞迴走Fail指標。如果走Fail指標走到了root節點,則跳過該字元,處理下一個字元。
因為AC自動機是沿著輸入文字的最長字尾移動的,所以在讀取完所有輸入文字後,最後遞迴走Fail指標,直到到達根節點,這樣可以檢測出所有的模式。
這個過程和KMP演算法的匹配也是非常相似,當然這一步就非常靈活了,我們需要通過多做題來提高熟練度。

Time Complexity Analyse

假設有N個模式串,平均長度為L;文章長度為M。

建立Trie樹:O(N*L)

建立fail指標:O(N*L)

模式匹配:O(M*L) (注:之所以要乘以一個L,是因為在統計的時候需要順著鏈回溯到root結點)

所以,總時間複雜度為:O( (N+M)*L )

Some Good Selection Of Standard Exercise

Entry:

synthesize problems: