解決的問題

KMP演算法用於單個字串匹配,AC自動機用於文章中匹配多個候選詞。

流程

第一步,先將候選詞先建立字首樹。

第二步,以寬度優先遍歷的方式把字首樹的每個節點設定fail指標, 頭節點的fail指標指向空, 頭節點孩子的fail指標指向頭, 其他節點的fail指標設定邏輯為:來到X節點的時候,是設定X的孩子的fail指標。

case 1:

假設X通過b指向了它的孩子,假設孩子為C,X的fail指標指向的節點假設為Y,Y有走向b的路,且Y走向b的路是指向的Z,那麼 C的fail指標指向Z,Y沒有走向b的路,那麼就看Y的fail指標指向的節點的fail指標有沒有走向b的路,依次往復,如果走到null都沒有,那麼進入case 2

case 2:

如果X的fail指標指向null,那麼就把X的孩子C指向頭節點

候選詞構造AC自動機的一些示例,其中虛線表示節點fail指標的指向位置,黑色點表示候選詞結尾位置。

示例一 ["abc","bkf","abcd","bkc"]

示例二 ["abcde","cde","e"]

示例三 ["abcde","bcde","cde","de","e"]

示例四 ["abcdef","cdef","ex"]

示例五 ["abcde","bcdf","cdtks"]

示例六 ["abc","abcde","abcd","bc","cd"]

示例七 ["abck","bct","st"]

fail指標的含義

假設要以這個字元結尾,哪一個另外的字尾串和其字首串完全相等

假設["abcde","bcde","cde","de","e"],所以abcde中e的fail指標指向bcde中的e,因為以abcde中的e的字尾有bcde和候選詞bcde的字首匹配最長。

匹配規則

每次來到一個節點,根據fail指標轉一圈,如果有描黑的點(結尾點)就收集答案,同時把結尾標誌為已處理(防止重複收集),匹配失敗的時候,要順著fail指標蹦到另外一條路徑上繼續匹配。

舉例

文章:"abcde"

候選詞:["abc","abcde","abcd","bc","cd"]

流程:

第一步,先對候選詞建立字首樹並連線好fail指標,建立好以後,如下圖

第二步,文章的逐個位置進行匹配。來到第一個字元a, 字首樹中有走向a字元方向的路。如下圖,走到2號點位置:

然後停在2號點位置,順著fail指標走一圈,如果有黑色點(結束點)就收集答案。所以,在2號點位置,順著fail指標走一圈分別要經過2號點,1號點,均不是結尾點,所以沒有答案收集。然後再匹配文章的下一個字元b, 字首樹來到如下3號位置節點:

然後停在3號節點,順著fail指標走一圈,分別會經歷7號節點和1號節點,均不是結尾點,所以未收集到答案。

繼續匹配文章下一個節點c,字首樹來到4號位置:

然後停在4號位置,順著fail指標走一圈,分別經歷了4號節點,8號節點,9號節點和1號節點,其中4號和8號是結尾點(表示abc的結尾和bc的結尾),所以收集到兩個答案abcbc

繼續匹配文章中的d字元,來到5號節點

然後停在5號節點上,順著fail指標走一圈,會經歷5,10,1號節點,5和10號節點分別是abcdcd的結尾,所以收集到了abcdcd兩個答案。

最後來到文章最後一個節點e,即到6號點位置

停在6號點位置,順著fail指標走,經過6號和1號,6號為abcde的結尾,所有收集到了abcde這個答案。

更多

演算法和資料結構筆記

參考資料

程式設計師程式碼面試指南(第2版)

演算法和資料結構體系班-左程雲