kmp:匹配單串,線性掃瞄,在失配時用next陣列引導j指標回溯,進行下一步匹配。
trie樹:多模式的匹配,構造26叉樹,同時記錄多個串的情況,記錄結尾,進行匹配。
kmp + trie樹 = ac自動機
ac自動機:給乙個字典,再給乙個文字,問這個文字裡出現了字典裡的哪些字。
可以用n個單詞的n次kmp演算法來做 o(n*m*單詞平均長度),
也可以用1個trie樹去匹配文字串的每個字母位置來做 o(m*每次字典樹遍歷的平均深度)。
在ac自動機中,我們首先將每個模式串插入到trie樹中,建立一棵trie樹,
然後構建fail指標(匹配失敗時用來引導p指標回溯,插穿在trie樹的各個節點之間的指標)。
類似kmp演算法中的next陣列,能在失配時跳轉到【具有最長公共前字尾】的字元繼續匹配。
如果跳轉,跳轉後的串的字首 必為 跳轉前的模式串的字尾(向上跳),
並且跳轉的新位置的深度(匹配字元個數)一定小於跳之前的節點。
1.將所有模式串構建成 trie 樹。
2.對 trie 上所有節點構建字首指標(類似kmp中的next陣列)
3.利用字首指針對主串進行匹配。
字典樹的構建過程是這樣的,當要插入許多單詞的時候,我們要從前往後遍歷整個字串,
當我們發現當前要插入的字元其節點再先前已經建成,我們直接去考慮下乙個字元即可,
當我們發現當前要插入的字元沒有再其前乙個字元所形成的樹下沒有自己的節點,
我們就要建立乙個新節點來表示這個字元,接下往下遍歷其他的字元。然後重複上述操作。
假設我們有下面的單詞,she , he ,say, her, shr ,我們要構建一棵字典樹。
在kmp演算法中,當我們比較到乙個字元發現失配的時候我們會通過next陣列,
找到下乙個開始匹配的位置,然後進行字串匹配,當然kmp演算法試用於單模式匹配。
所謂單模式匹配,就是給出乙個模式串,給出乙個文字串,尋找是否包含模式串。
ac自動機中,有fail指標,當發現失配的字元失配的時候,跳轉到fail指標指向的位置,
然後再次進行匹配操作,ac自動機之所以能實現多模式匹配,就歸功於fail指標的建立。
當前節點t有fail指標,其fail指標所指向的節點和t所代表的字元是相同的。
因為t匹配成功後,我們需要去匹配 t->child,發現失配,那麼就從t->fail開始再次匹配。
fail指標的求法:bfs。直接與根節點相連的節點失配,他們的fail指標直接指向root。
其他節點的fail指標:假設當前節點為father,其孩子節點記為child。
求child的fail指標時,首先我們要找到其father的fail指標所指向的節點t,
看t的孩子中有沒有和child節點所表示的字母相同的節點,如果有、就是child的fail指標;
如果沒有,找father->fail->fail,重複過程,直到到達root(指向root)。
(1)當前字元匹配,表示從當前節點沿著樹邊有一條路徑可以到達目標字元,
如果當前匹配的字元是乙個單詞的結尾,我們可以沿著當前字元的fail指標,一直遍歷到根,
如果這些節點末尾有標記(標記代表節點是乙個單詞末尾),遍歷到的都是可以匹配上的節點。
統計完畢後標記。此時沿該路徑走向下乙個節點繼續匹配,目標指標移向下個字元。
(2)當前字元不匹配,則去當前節點fail指標所指向的字元繼續匹配,直到指標指向root。
重複這2個過程中的任意乙個,直到文字串走到結尾為止。
對照上圖,看一下模式匹配這個詳細的流程,其中文字串為 yasherhs(某文章)。
對於i=0,1,trie 中沒有對應的路徑,故不做任何操作;
i=2,3,4時,指標p走到左下節點e。因為節點e的 count 資訊為1,所以cnt+1,
(到達某乙個單詞的末尾,該資訊用bool tail [ ] 記錄,單詞數++)。
並且將節點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時,找不到任何匹配,結束。
//trie字典樹:
int tot=1,trie[maxn][26
];bool tail[maxn]; //
串尾元素標記
void make_trie(char* s) tail[p]=true; //
標記串尾元素
}
//fail指標:(名稱可以用nextt陣列代替)
intnextt[maxn],que[maxn];
void
bfs()}}
}
//匹配是否存在:
int find1() return
true;}
//void find2(char *s)
p=trie[p][c]; //
向下層尋找匹配字元編號
}}
——時間劃過風的軌跡,那個少年,還在等你。
AC自動機總結
講解 ac自動機講解1 ac自動機講解2 1.模版題 hdu2222 include include include using namespace std int k int n char s 10010 60 char mat 1100000 int cnt struct node trie 1...
AC自動機總結
考慮kmp問題的公升級版,即有多個模式串,單個文字串。問匹配次數。考慮對於每乙個模式串建乙個 fail 然後對於每乙個模式串都和文字串暴力跑。前置知識 trie樹,bfs 沒什麼好說的。演算法實現 我們考慮將所有的模式串放到一顆 trie 樹,如果匹配失敗的話轉移到 fail 指標上面去,這樣子複雜...
AC自動機 建立nlogn個AC自動機
string set queries 題意 給你3種操作,1 加入乙個串到集合中。2 刪除集合中的某乙個串 3 查詢集合中的字串在給定的字串種出現幾次。同乙個串可重複 解法 建立多個ac自動機,用二進位制分組來處理。加入給你21個串 分為 16 4 1,再新增乙個串的時候,即21 1,22 16 4...