多模式匹配ac演算法的核心仍然是尋找模式串內部規律,達到在每次失配時的高效跳轉。這一點與單模式匹配kmp演算法和bm演算法是一致的。不同的是,ac演算法尋找的是模式串之間的相同字首關係。ac演算法的核心是三張查詢表:goto、failure和output,共包含四種具體的演算法,分別是計算三張查詢表的演算法以及ac演算法本身。
構造goto表
goto表本質上是乙個有限狀態機,這裡稱作模式匹配機(pattern matching machine,pmm)。下面以**中的例子來說明goto表的構造過程。對於模式串集合k
第一步:pmm初始狀態為0,然後向pmm中加入第乙個模式串k[0] = "he"。
第二步:繼續向pmm中新增第二個模式串k[1] = "she",每次新增都是從狀態0開始掃瞄。
第三步:從狀態0開始繼續新增第三個模式串k[2] = "his",這裡值得注意的是遇到相同字元跳轉時要重複利用以前已經生成的跳轉。如這裡的'h'在第一步中已經存在。
第四步:新增模式串k[3] = "hers"。至此,goto表已經構造完成。
構造failure表
failure表作用是在goto表中匹配失敗後狀態跳轉的依據,這點與kmp中next表的作用相似。首先引入狀態深度的概念,狀態s的深度depth(s)定義為在goto表中從起始狀態0到狀態s的最短路徑長度。如goto表中狀態1和3的深度為1。
構造failure表利用到了遞迴的思想。
1、若depth(s) = 1,則f(s) = 0;
2、假設對於depth(r) < d的所有狀態r,已近計算出了f(r);
3、對於深度為d的狀態s:
(1) 若g(r,a) = fail,對於所有的a,則不動作;(注:a為字元,g為狀態轉移函式);
(2) 否則,對於a使得g(r,a) = s,則如下步驟:
a、使state = f(r)
b、重複步驟state = f(state),直到g(state, a) != fail。(注意對於任意的a,狀態0的g(0,a) != fail)
c、使f(s) = g(state, a)。
根據以上演算法,得到該例子的failure表為:
i 1 2 3 4 5 6 7 8 9
f(i) 0 0 0 1 2 0 3 0 3
構造output表
output表示輸出,即代表到達某個狀態後某個模式串匹配成功。該錶的構造過程融合在goto表和failure表的構造過程中。
1、在構造goto表時,每個模式串結束的狀態都加入到output表中,得到
i output(i)
2
5
7
9
2、在構造failure表時,若f(s) = s',則將s和s『對應的output集合求並集。如f(5) = 2,則得到最終的output表為:
i output(i)
2
5
7
9
ac演算法實現
根據上面已經構造好的goto、failure和output表就可以方便地應用ac演算法了。
剩下的工作就是將目標串依次輸入到pmm(即goto表),然後在發生失配的時候查詢failure表實現跳轉,在輸出狀態查詢output表輸出結果(包括匹配的串的集合和目標串中的位置)。以字串"ushers"為例。狀態轉移如下:
u s h e r s
0 0 3 4 5 8 9 2
說明:在狀態5發生失配,查詢failure表,轉到狀態2繼續比較。在狀態5和狀態9有輸出。
演算法改進
值得注意的是在ac演算法的以上實現中,對於輸入字元a的跳轉次數是不確定的。因為有可能在輸入a後發生失配,需要查詢failure表重新跳轉。能不能在pmm的基礎上實現確定型的有限狀態機,即對於任意字元a,都只用進行一次確定的狀態跳轉?答案是肯定的。在aho和corasick**中給出了處理的方法:構造乙個與kmp演算法中相似的next表,實現確定性跳轉。
next表的構造需要在goto表和failure表的基礎上得到。next表如下所示:
輸入字元 下一狀態
state 0: h 1
s 3
* 0
state 1: e 2
i 6
h 1
s 3
* 0
state9,7,3: h 4
s 3
* 0
state5,2: r 8
h 1
s 3
* 0
state 6: s 7
h 1
* 0
state 4: e 5
i 6
h 1
s 3
* 0
state 8: s 9
h 1
* 0
注:*表示除了以上字元以外的其他字元。儲存next陣列所需要的記憶體空間比儲存goto表更大。這樣就可以用next表替代goto表和failure表,實現每次字元輸入的唯一跳轉。
AC演算法初探
ac演算法初探 一 什麼是ac演算法 ac演算法,即aho corasick自動機演算法。該演算法一次遍歷原串便可定位所有模式串在原串中出現的位置。該演算法通過所有的模式串構建乙個有限狀態自動機,然後用這個自動機去處理原串 只要一次遍歷即可 二 ac演算法流程 ac演算法總共由三部分組成,分別是a ...
演算法思想 滑動視窗思想
在解leetcode題的時候,遇到了幾個新的演算法思想,這個系列文章就把leetcode中的一些演算法思想做一些整理,包括老生常談的動態規劃,也包括我最新接觸的滑動視窗思想,並查集等,另外,遇到新的題目的時候也會在這裡做一些整理。起源 計算機網路協議 在介紹滑動視窗思想之前,首先介紹這個演算法思想的...
矩陣乘法AC演算法
總時間限制 1000ms 記憶體限制 65536kb 描述 計算兩個矩陣的乘法。n m階的矩陣a乘以m k階的矩陣b得到的矩陣c 是n k階的,且c i j a i 0 b 0 j a i 1 b 1 j a i m 1 b m 1 j c i j 表示c矩陣中第i行第j列元素 輸入第一行為n,m,...