AC自動機講解

2021-06-23 07:17:21 字數 2840 閱讀 5668

**:飄過的小牛

ac自動機簡介:

首先簡要介紹一下ac自動機:aho-corasick automation,該演算法在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自動機入門知識就講完了。hdu 2222入門題

ac自動機貌似還有很多需要優化的地方,等把基礎搞定之後再學習一下怎麼優化吧。。

AC自動機講解

首先,作為作者的我一定知道你已經會了這兩個演算法 kmp與trie樹,如若不會,可以先學習一下。我在這裡宣告一下ac自動機不是自動ac的演算法,其全稱是aho corasick automaton,是一種著名的多模匹配演算法。其實現類似於trie樹與kmp演算法的結合,是將多個模式串放在trie樹上...

AC自動機 講解 模板

首先 先給你q 個查詢串 再給你乙個主串s 或者很多個不同主串 q個查詢串 有幾個 在主串裡 匹配成功了 可以記個cnt統計 查詢串不重複,重複的要計算數量的話,要加個sum記錄 重複查詢串 出現了幾次 還可以知道 匹配成功 的查詢串是哪些 偷懶還用 sum標 它是第幾個查詢串 字典樹就不用說了吧,...

AC自動機 建立nlogn個AC自動機

string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...