ac自動機這個東西,聽起來很高大上,在高中的時候不知道什麼是自動機,以為寫出了ac自動機就可以自動ac……
現在知道了它是用來解決字串匹配問題的東西,說白了就是kmp+trie。這個在去年暑假的時候,hc學長也略微提到過,但是沒有具體的講。
在解決只有乙個模式串的匹配問題的時候,我們用樸素的kmp演算法即可快速完成,但是,如果有很多個匹配串呢?這是就得用上ac自動機(ac_automation)。大致思路就是,在kmp中,我們失配的時候有乙個next陣列,表示下乙個匹配要把原串往後滑動多少位,也即與最長公字首有關。現在有多個模式串,那麼我滑動的時候就要考慮多個東西的最長公共字首,對於每乙個模式串的字首都要進行嘗試匹配,而且匹配的時候,是要與所有的模式串匹配而不只是單個。所以說,我們先用trie字典樹儲存所有的模式串,然後一次掃過所有的模式串。之後每乙個點設定乙個fail指標,表示失配之後應該匹配字首相同的另乙個模式串的位置。然後類似kmp演算法,從頭開始匹配,匹配成功則繼續,否則滑動到fail的位置繼續嘗試,直到滑動回了根節點。時間複雜度為o(len),len表示所有串的長度。
首先是構建trie和fail指標。構建trie和普通的trie區別不大,關鍵是fail指標,這個具體的我就盜別人一張圖了,希望不要介意。
這裡有abcd、abd、cd和bcd四個模式串,那麼我的fail指標就按照圖中那麼設定,圖中只畫了c的,可以看到,當串的字尾與fail所指向的串的字首有公共部分,且這兩個一定是最長的。如果是在找不到公共部分,那麼就fail指向根節點。具體實現的話,我們通常使用廣搜迭代的方法。具體**如下(以26個小寫字母為例):
void ins(char* x)
else t[t[o].ch[i]].fail=root;
q.push(t[o].ch[i]);
} q.pop();}}
然後就是匹配了。匹配正如之前說的,如果能配上,那麼直接往後走,否則就往fail指標走,一直走到root為止。唯一需要注意的是每次匹配上之後,都要走一次fail指標,把所有相互包含的模式串也要計算進去。具體見**:
int ac_automation(char *x)
t[250000];
int tot,root;
void init()
void ins(char* x)
else t[t[o].ch[i]].fail=root;
q.push(t[o].ch[i]);
} q.pop();}}
int ac_automation(char *x)
scanf("%s",s);
trie.get_fail();
printf("%d\n",trie.ac_automation(s));
}return 0;
}
AC自動機模板
ac自動機模板 ac自動機模板 使用方法 1 init 初始化函式 2 insert str 插入字串函式 3 build 構建ac自動機 4 query str 返回出現的字串個數 使用需注意事項 1 注意輸入的字元的範圍,需對next和其二維大小及相關引數進行更改 2 注意next fail和e...
AC自動機模板
ac自動機主要是用於多模式串的匹配問題,按照我的理解,ac自動機就是在tire樹上實現kmp演算法,由於ac自動機加入了失敗指標,所以可以把他看成乙個狀態轉移的圖。給出模板 include include include include includeusing namespace std cons...
模板 AC自動機
我覺得ac自動機的難點和核心是構建失敗指標,父親的失敗指標的兒子 son2 中有和兒子 son1 相同的,即為son1的失敗指標 例 還是有個不懂的地方 第90行,跪求大佬賜教 include include include include include include include inclu...