AC自動機演算法

2021-06-20 02:06:41 字數 2755 閱讀 8843

**:

ac自動機簡介:

首先簡要介紹一下ac自動機:aho-corasickautomation,該演算法在2023年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹trie和kmp模式匹配演算法的基礎知識。kmp演算法是單模式串的字元匹配演算法,ac自動機是多模式串的字元匹配演算法。

ac自動機的構造:

1.構造一棵trie,作為ac自動機的搜尋資料結構。

2.構造fail指標,使當前字元失配時跳轉到具有最長公共前字尾的字元繼續匹配。

如同 kmp演算法一樣,ac自動機在匹配時如果當前字元匹配失敗,那麼利用fail指標進行跳轉。由此可知如果跳轉,跳轉後的串的字首,必為跳轉前的模式串的字尾並且跳轉的新位置的深度(匹配字元個數)一定小於跳之前的節點。所以我們可以利用bfs在 trie上面進行 fail指標的求解。

3.掃瞄主串進行匹配。

ac自動機詳講:

我們給出5個單詞,say,she,shr,he,her。給定字串為yasherhs。問多少個單詞在字串中出現過。

一、trie

首先我們需要建立一棵trie。但是這棵trie不是普通的trie,而是帶有一些特殊的性質。

首先會有3個重要的指標,分別為p, p->fail, temp。

1.指標p,指向當前匹配的字元。若p指向root,表示當前匹配的字串行為空。(root是trie入口,沒有實際含義)。

2.指標p->fail,p的失敗指標,指向與字元p相同的結點,若沒有,則指向root。

3.指標temp,測試指標(自己命名的,容易理解!~),在建立fail指標時有尋找與p字元匹配的結點的作用,在掃瞄時作用最大,也最不好理解。

對於trie樹中的乙個節點,對應乙個序列s[1...m]。此時,p指向字元s[m]。若在下乙個字元處失配,即p->next[s[m+1]]==null,則由失配指標跳到另乙個節點(p->fail)處,該節點對應的序列為s[i...m]。若繼續失配,則序列依次跳轉直到序列為空或出現匹配。在此過程中,p的值一直在變化,但是p對應節點的字元沒有發生變化。在此過程中,我們觀察可知,最終求得得序列s則為最長公共字尾。另外,由於這個序列是從root開始到某一節點,則說明這個序列有可能是某些序列的字首。

再次討論p指標轉移的意義。如果p指標在某一字元s[m+1]處失配(即p->next[s[m+1]] ==null),則說明沒有單詞s[1...m+1]存在。此時,如果p的失配指標指向root,則說明當前序列的任意字尾不會是某個單詞的字首。如果p的失配指標不指向root,則說明序列s[i...m]是某一單詞的字首,於是跳轉到p的失配指標,以s[i...m]為字首繼續匹配s[m+1]。

對於已經得到的序列s[1...m],由於s[i...m]可能是某單詞的字尾,s[1...j]可能是某單詞的字首,所以s[1...m]中可能會出現單詞。此時,p指向已匹配的字元,不能動。於是,令temp= p,然後依次測試s[1...m], s[i...m]是否是單詞。

構造的trie為:

二、構造失敗指標

用bfs來構造失敗指標,與kmp演算法相似的思想。

首先,root入隊,第1次迴圈時處理與root相連的字元,也就是各個單詞的第乙個字元h和s,因為第乙個字元不匹配需要重新匹配,所以第乙個字元都指向root(root是trie入口,沒有實際含義)失敗指標的指向對應下圖中的(1),(2)兩條虛線;第2次進入迴圈後,從佇列中先彈出h,接下來p指向h節點的fail指標指向的節點,也就是root;p=p->fail也就是p=null說明匹配序列為空,則把節點e的fail指標指向root表示沒有匹配序列,對應圖-2中的(3),然後節點e進入佇列;第3次迴圈時,彈出的第乙個節點a的操作與上一步操作的節點e相同,把a的fail指標指向root,對應圖-2中的(4),併入隊;第4次進入迴圈時,彈出節點h(圖中左邊那個),這時操作略有不同。由於p->next[i]!=null(root有h這個兒子節點,圖中右邊那個),這樣便把左邊那個h節點的失敗指標指向右邊那個root的兒子節點h,對應圖-2中的(5),然後h入隊。以此類推:在迴圈結束後,所有的失敗指標就是圖-2中的這種形式。

三、掃瞄

構造好trie和失敗指標後,我們就可以對主串進行掃瞄了。這個過程和kmp演算法很類似,但是也有一定的區別,主要是因為ac自動機處理的是多串模式,需要防止遺漏某個單詞,所以引入temp指標。

匹配過程分兩種情況:(1)當前字元匹配,表示從當前節點沿著樹邊有一條路徑可以到達目標字元,此時只需沿該路徑走向下乙個節點繼續匹配即可,目標字串指標移向下個字元繼續匹配;(2)當前字元不匹配,則去當前節點失敗指標所指向的字元繼續匹配,匹配過程隨著指標指向root結束。重複這2個過程中的任意乙個,直到模式串走到結尾為止。

對照上圖,看一下模式匹配這個詳細的流程,其中模式串為yasherhs。對於i=0,1。trie中沒有對應的路徑,故不做任何操作;i=2,3,4時,指標p走到左下節點e。因為節點e的count資訊為1,所以cnt+1,並且講節點e的count值設定為-1,表示改單詞已經出現過了,防止重複計數,最後temp指向e節點的失敗指標所指向的節點繼續查詢,以此類推,最後temp指向root,退出while迴圈,這個過程中count增加了2。表示找到了2個單詞she和he。當i=5時,程式進入第5行,p指向其失敗指標的節點,也就是右邊那個e節點,隨後在第6行指向r節點,r節點的count值為1,從而count+1,迴圈直到temp指向root為止。最後i=6,7時,找不到任何匹配,匹配過程結束。

AC自動機演算法

ac自動機簡介 首先簡要介紹一下ac自動機 aho corasick automation,該演算法在1975年產生於貝爾實驗室,是著名的多模匹配演算法之一。乙個常見的例子就是給出n個單詞,再給出一段包含m個字元的文章,讓你找出有多少個單詞在文章裡出現過。要搞懂ac自動機,先得有字典樹trie和km...

演算法 AC自動機

這篇部落格拖了好久好久,真是尷尬,原因大概是我感覺很多東西,都是直覺,有種只可意會不可言傳的味道,想完全搞懂,但後來仔細想想,ac自動機好像本來就不是乙個非常非常確定的演算法,比如說,我該拿覺很多情況可以把演算法卡成n 2。所以拖了很久,醬紫。先談談ac自動機是什麼。我們知道kmp,可以快速的對乙個...

AC自動機演算法

簡而言之,就是在kmp演算法的思想上加上trie樹來實現的乙個適合多個模式串的匹配問題。kmp演算法時間複雜度優秀的原因是有乙個next陣列,也叫做失配指標陣列,使得匹配的時間複雜度嚴格o m n o m n o m n ac自動機也有這樣的陣列來在失配的時候去跳到相應應該去的地方。所以,ac自動機...