非常經典的乙個關於字串匹配的演算法
前置技能是:kmp和trie
重難點是fail指標(其實挺簡單的)
其實不一定要會kmp,只要會它的思想就行了。
所謂fail邊,其實就是乙個失敗指標,與kmp的next指標(類似於失敗指標,詳見我的kmp的部落格裡的p陣列)不同的是,next是對於乙個串而言的,而fail則是對全部串都通用,而且是在trie上操作的。
fail[i]表示某乙個節點,根節點(以下簡稱root)到另外乙個節點所組成的字串,可以完全匹配與i的祖先到i所組成的字串,這樣說有點玄學,給個圖深入了解一下吧。
如圖,這是一棵trie,然後我們人工腦補它們的fail邊。
為什麼只連了c,d呢,想想看,root到編號為5的c所構成的串就是「c」,正好符合編號為2的c它自己。
還有root到編號為6的d,構成了「cd」,編號為3的d的祖先到編號為3的d所構成的,也正好是「cd」。
但是有的節點沒有匹配怎麼辦呢,那就直接把fail邊連到root就好啦,於是圖變成了這樣。
ok,現在我們想一想怎麼連fail邊。
對於乙個節點,如果它的fail邊不連向root,那麼它所連向的節點可能是它父親的fail所連向的節點的兒子,因為只有在前面都匹配了的情況下,才能去匹配這個節點是否也可以嘛。
為什麼是可能呢,因為有可能匹配不了,怎麼辦呢?那就從它父親的fail邊指向的節點的fail邊指向的節點再去找,依次類推,一直到到root為止。
ps:在root這個點也要再匹配一次!root的fail邊指向自己。
給出程式了解一下。
while(h0)then
begin
inc(t);
d[t]:=trie[d[h],i];
if(d[h]<>0)then
begin
x:=fail[d[h]];
while(trie[x,i]=0)and(x<>0)do x:=fail[x];
//一直去匹配,用它父親的fail去找
if(trie[x,i]<>0)then
begin
fail[d[t]]:=trie[x,i];
inc(into[trie[x,i]]);
//記錄下入度,後面有用的
end;
end;
end;
end;
end;
一定要學會trie先!!!!(不會可以去看我的trie) ac自動機 匹配最長字首 多模匹配 AC自動機
精確的字串匹配演算法有 單模匹配演算法,比如,kmp bm演算法等 和 多模匹配演算法,比如,wu manber ac演算法等。ac演算法 aho corasick 是kmp演算法向多模式串情形的擴充套件,該演算法使用一種特殊的自動機,即ac自動機。ac自動機由一組模式串p生成,是trie的擴充套件...
AC自動機 多模匹配演算法
寫了個模板題,加強版借鑑大佬的 前置技能kmp 感覺沒啥用主要是思想 字典樹。p3808 模板 ac自動機 簡單版 include include include include include include include include using namespace std typedef ...
AC 自動機 多模式串匹配
上的敏感詞過濾是怎麼實現的呢?實際上,這些功能最基本的原理就是字串匹配演算法,也就是通過維護乙個敏感詞的字典,當使用者輸入一段文字內容後,通過字串匹配演算法來檢查使用者輸入的內容是否包含敏感詞。bf rk bm kmp 演算法都是針對只有乙個模式串的字串匹配演算法,而要實現乙個高效能的敏感詞過濾系統...