1. 程式人生 > >AC自動機概述

AC自動機概述

首先我們需要了解trie樹。
我們把每個模式串逐個插入trie樹。
比如說把a,aba,ac,cb四個串插入trie樹,得到的是這樣的:
這裡寫圖片描述

對於trie樹來說,我們從根開始到每一個結束節點(紅色節點)的路徑都代表一個字串。為了減少狀態我們把有相同字首的字串的前綴合並。插入時標出結束節點。

fail鏈:

在AC自動機中最重要的就是fail鏈了。fail鏈中文就是失配鏈。AC自動機不像字尾自動機一樣,AC自動機構建出來就是用來匹配的。當我們用文字串進行匹配的時候,到達一個狀態表示當前位置匹配的最長串。如果下一步沒有轉移了我們就要縮短當前的匹配長度再尋找轉移。fail鏈應該指向在AC自動機出現的它的最長字尾。

構造:

當我們構造出一個trie樹之後怎麼構造一個AC自動機?其實很好理解,假如我知道父親的fail鏈指向,只需要沿著父親的fail鏈向上找有沒有一個和自己一樣的轉移。如果有就連fail。因為可以遍歷父親串的在AC自動機裡出現所有後綴串。

現在我們構造一下剛剛trie樹的Ac自動機:
這裡寫圖片描述

稍微講一下演算法流程:

bfs構圖,可以做到先構造父親載構造兒子,到達一個節點遍歷所有兒子,每遍歷一個兒子順著fail鏈向上找有無轉移即可。
注意root的兒子事先指向root。

一些小trick:

注意匹配到一個節點時它沿fail鏈向上的所有節點都會被匹配,所以可以在匹配之前先下推結束狀態保證複雜度。

AC自動機只能離線構造,不支援線上插入,因為這樣會打亂AC自動機的fail。但是可以利用分塊的思想使複雜度降成 n n 。具體做法就是開AB兩個字尾自動機,每次插入B自動機,當B中有

n 個串之後把B併入A並清空B。查詢就在AB裡均匹配一次,把答案加起來即可。