AC自動機+trie樹實現高效多模式匹配字典

前言

常常會遇到一類需求,在一段字符串中查找全部能匹配上的模式,好比查找一段文字匹配上字典中哪些短語。這時爲了高效處理,就會考慮 AC 自動機,即 Aho-Corasick 自動機算法。它的核心思想是經過有限自動機巧妙地將字符比較轉化爲了狀態轉移。java

經過 AC 自動機能作到匹配時不須要回溯,並且時間複雜度爲 O(n),即時間複雜度與詞典的規模無關。git

暴力匹配

暴力匹配就是一個一個比較,將模式串從頭至尾匹配主串字符串,以下圖模式串"ABCE"比較主串,一旦遇到不相同的則日後移覺得,從新開始比較,直到比對完主串,接着第二個模式串繼續比較。該方法簡單暴力,很好理解,但時間複雜度高,O(mn)。github

image

AC自動機

AC自動機主要是將 n 個模式串構建成一個肯定性的樹形有限狀態機,而後將主串做爲該有限狀態機的輸入,使該狀態機進行狀態的轉換,當到達某些特定的狀態時則說明發生模式匹配。算法

經過例子來理解,以 he、she、his、hers 爲模式串,ushers爲主串,構成了以下的狀態機。bash

image

在狀態機內部,能夠看到有實線和虛線箭頭,優先以實線標明方向轉換狀態,當沒法實線轉換時才使用虛線轉換。併發

另外,當轉換到圖中紅圈位置時說明發生了模式匹配,好比對於he,從根節點到1再到2,此時符合he,說明發生了模式匹配。機器學習

根據上圖你能夠試試看ushers會匹配出哪些模式,而且比劃下狀態的轉換過程。分佈式

AC的三個函數

AC自動機包含了三個核心函數,基本上理解了他們就搞懂AC了。函數

  • goto函數,用來指導狀態轉換,即在當前狀態下,輸入一個字符後該轉到哪一個狀態,對應的是上圖中的實線部分。

image

  • failure函數,用來指導匹配失敗時的狀態轉換,即在當前狀態下,輸入一個字符後沒辦法根據實線進行轉換了,此時根據虛線進行轉換,對應上圖虛線部分。

image

  • output函數,描述哪些狀態下發生了匹配,匹配的模式是什麼。

image

實現

實現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。

-------------推薦閱讀------------

個人2017文章彙總——機器學習篇

個人2017文章彙總——Java及中間件

個人2017文章彙總——深度學習篇

個人2017文章彙總——JDK源碼篇

個人2017文章彙總——天然語言處理篇

個人2017文章彙總——Java併發篇


跟我交流,向我提問:

公衆號的菜單已分爲「讀書總結」、「分佈式」、「機器學習」、「深度學習」、「NLP」、「Java深度」、「Java併發核心」、「JDK源碼」、「Tomcat內核」等,可能有一款適合你的胃口。

爲何寫《Tomcat內核設計剖析》

歡迎關注:

相關文章
相關標籤/搜索