解決的問題
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的結尾),所以收集到兩個答案abc
和bc
。
繼續匹配文章中的d字元,來到5號節點
然後停在5號節點上,順著fail指標走一圈,會經歷5,10,1號節點,5和10號節點分別是abcd
和cd
的結尾,所以收集到了abcd
和cd
兩個答案。
最後來到文章最後一個節點e,即到6號點位置
停在6號點位置,順著fail指標走,經過6號和1號,6號為abcde
的結尾,所有收集到了abcde
這個答案。