AC自動機 學習筆記

2021-07-28 01:12:49 字數 1970 閱讀 1282

是一種數學模型,大概就是由一堆狀態和狀態轉移規則等東西構成,能與外界交換資訊,並改變動作。

這個是理論上的東西,了解就行,對ac自動機的理解沒有大影響。

通俗的講就是在trie上做kmp,處理多模式串匹配問題。

trie 的每個結點就是乙個狀態,根結點是初始狀態。

ac自動機的行為被定義為一下3個函式:

1. next函式 ch(q,a):返回從當前狀態q走值為a的邊後所到達的狀態。如果根節點沒有值為a的邊,那麼ch(0,a)=0,(就是說:當讀入不匹配的字元時,自動機保持在初始狀態)

如果從結點q出發有一條邊值為a到達結點v,那麼 ch(q,a)=v,否則ch(q,a)=φ。

2. fail函式 fail(q):返回從狀態q(q!=root)匹配錯誤時要轉移到的狀態

記l(q)表示trie上q節點對於的字串,

如果l(v)是l(q)的乙個字尾,且是最長的字尾,則fail(q)=v(kmp的思想)。

fail(q)總是能返回乙個狀態,因為l(root)=φ是任何模式串的字首

3. output函式out(q):輸出在狀態q時,所有匹配的模式串。

上面的描述比較形式化。簡單來說:

先把所有待匹配串插入到一顆trie中。

對於每個節點,我們需要額外計算一些資訊:

fail指標:如上所述,類似kmp中的next表。

cnt : 若這個位置是某個模式串的結尾,就cnt++。

last指標:指向沿著當前節點的fail指標往回走,第乙個遇到的cnt>0的節點。是用於output的。

假設我們已經構造出了這些資訊。考慮如何進行匹配,大概流程是這樣的:

根據目標串乙個乙個字元在trie上走,

每走到乙個節點,執行一次output(順著last指標往後累加答案)。走到下個節點時,如果ch(p,s[i])不為空則直接走過去,否則沿著fail指標走,直到匹配成功或者到初始狀態(還是kmp)

注意到「沿著fail指標走,直到匹配成功或者到初始狀態」這個過程較繁瑣,而且只有ch(p,s[i])為空時才會執行,就想到可以優化一下,直接把ch(p,s[i])指到要跳到的節點。

**如下:

int find(p_node p)  

int query(char* s)

回到如何構造這些資訊,顯然都可以一次對trie的bfs遍歷實現,具體對於p的某個兒子v:

v->fail=p->fail->ch[i];

v->last=(v->fail->cnt?v->fail:v->fail->last);

要注意的是root的直接兒子的fail和last都指向root。

理解定義後還是比較顯然的。

模板題pdu2222**:

#include

#include

#include

#include

using namespace std;

struct node base[500000], *len, nil, *null=&nil, *root;

typedef node* p_node;

p_node newnode(node* son=null)

void insert(p_node &p,char *now)

insert(p->ch[(*now)-'a'],now+1);

}queueque;

void build() else root->ch[i]=root;

while(!que.empty()) else p->ch[i]=p->fail->ch[i];

}}int find(p_node p)

int query(char* s)

int _test,n,m;

char s[1000005];

int main()

return

0;}

AC自動機學習筆記

ac自動機是基於字典樹和fail指標來快速一類解決多串匹配的問題。先用所有模式串建乙個字典樹。然後用bfs搞出每個節點的fail指標。fail指標是指向 和當前 字首的字尾有最長匹配的字首。洛谷3808 掃文字串的時候,標記一下訪問過的字典樹上的節點。include using namespace ...

AC自動機學習筆記

title ac自動機學習筆記 date 2020 08 31 15 53 40 tags 8月的最後一天,還是完成了ac自動機的學習。在熟練掌握了kmp後,我發現ac自動機並沒有想象的那麼難,既不難理解,也不難實現,於是決定寫點東西記錄一下。本篇主要談談ac自動機的理論,思想。首先我們必須要明確乙...

AC自動機學習筆記

先簡單複習一下學習ac自動機所需要的字首知識。字首知識 1 trie樹 字典樹,也稱trie樹,字首樹,主要用於儲存大量的字串以及查詢操作。對於trie樹,一般有兩個操作 舉個例子,對於這樣幾個字串,我們看他們在trie樹中是如何儲存的 這裡需要注意,字元是邊,而不是節點,但都是一一對應的 int ...