常常會遇到一類需求,在一段字符串中查找全部能匹配上的模式,好比查找一段文字匹配上字典中哪些短語。這時爲了高效處理,就會考慮 AC 自動機,即 Aho-Corasick 自動機算法。它的核心思想是經過有限自動機巧妙地將字符比較轉化爲了狀態轉移。java
經過 AC 自動機能作到匹配時不須要回溯,並且時間複雜度爲 O(n),即時間複雜度與詞典的規模無關。git
暴力匹配就是一個一個比較,將模式串從頭至尾匹配主串字符串,以下圖模式串"ABCE"比較主串,一旦遇到不相同的則日後移覺得,從新開始比較,直到比對完主串,接着第二個模式串繼續比較。該方法簡單暴力,很好理解,但時間複雜度高,O(mn)。github
AC自動機主要是將 n 個模式串構建成一個肯定性的樹形有限狀態機,而後將主串做爲該有限狀態機的輸入,使該狀態機進行狀態的轉換,當到達某些特定的狀態時則說明發生模式匹配。算法
經過例子來理解,以 he、she、his、hers
爲模式串,ushers
爲主串,構成了以下的狀態機。bash
在狀態機內部,能夠看到有實線和虛線箭頭,優先以實線標明方向轉換狀態,當沒法實線轉換時才使用虛線轉換。併發
另外,當轉換到圖中紅圈位置時說明發生了模式匹配,好比對於he
,從根節點到1再到2,此時符合he
,說明發生了模式匹配。機器學習
根據上圖你能夠試試看ushers
會匹配出哪些模式,而且比劃下狀態的轉換過程。分佈式
AC自動機包含了三個核心函數,基本上理解了他們就搞懂AC了。函數
實現AC自動機時通常都會用TRIE樹結構,那麼就會定義一個ACTrieNode
類,包含了子節點、值、output、failure節點等等屬性。學習
public class ACTrieNode {
private ACTrieNode[] children;
private byte[] value;
private boolean deleted = false;
private int status;
private ACArray[] results = null;
private ACTrieNode failureNode;
private static String encoding = "utf-8";
}
複製代碼
詳細實現看github,https://github.com/sea-boat/TextAnalyzer/blob/master/src/main/java/com/seaboat/text/analyzer/segment/ACTrieTree.java。
-------------推薦閱讀------------
跟我交流,向我提問:
公衆號的菜單已分爲「讀書總結」、「分佈式」、「機器學習」、「深度學習」、「NLP」、「Java深度」、「Java併發核心」、「JDK源碼」、「Tomcat內核」等,可能有一款適合你的胃口。
歡迎關注: