題目傳送門
終於看懂啦!終於學會了ac自動機啦!(flag立起)寫篇部落格梳理一下自己的思路吧。
在文章的開頭,必須先放上一些大佬的部落格來壓壓場面:當然是orz zzk大佬,神犇傳送門
然而ac自動機的原理其實是比較好理解的,就是把trie樹和kmp的思想結合起來。這麼說起來kmp就是單個字串的ac自動機啊。(霧)
給出許多模式串,把這些字串都加入到trie樹中,在每個字串結尾的葉子節點上計數。
然後在所有模式串都加入trie樹中後開始建立next樹,也就是對於所有的模式串做kmp。
首先把和根節點直接相連的節點加入佇列中,然後用bfs的思想來確定每個節點的next:取當前的隊頭,然後列舉這個節點的所有兒子,設當前兒子的字母為ch,當前節點的next為k,取所有存在的兒子,若節點k的ch兒子不為空,則當前節點的兒子的next就等於節點k的ch兒子的編號,否則k=next[k],即保證節點k到根的路徑是當前節點到根節點路徑的字尾,重複上述操作,直到確定了當前節點的ch兒子。
不過上述求next樹的方法過於暴力,可能會tle,那麼我們就會想到上述操作是否有可以優化的地方,答案當然是有的。
依然是去當前的隊頭,列舉這個節點的所有兒子,若這個兒子存在,那麼這個兒子的next就等於節點k的ch兒子,否則這個兒子就等於節點k的ch兒子。
為什麼這樣的操作可以保證正確性呢?因為我們可以考慮節點k的ch兒子,如果節點k的ch兒子不存在,則把它變成了乙個指標,指向它如果存在時匹配的節點。
這樣搞了以後就非常方便,不需要每次再向上列舉,浪費時間。
最後就是查詢,這題的查詢就是求給定的字串中包含了多少模式串,只要每次向上列舉,答案加上當前節點的計數,然後把當前節點標記為不可取即可。
附上ac**:
#include #include #include using namespace std;
const int n=1000010;
struct noteac[n];
int n,size=0;
char s[n];
inline void insert(char *s)
++ac[now].ed;
return;
}inline void build()
return;
}inline int query(char *s)
return ans;
}int main(void)
洛谷3808 模板 AC自動機(簡單版)
題目大意 給定 n 個模式串 p sum p i le10 6 和乙個 t t le10 6 求在 t 中被匹配的 p 的個數。思路 ac自動機模板題,注意 t 中乙個字元可能對應自動機上多個結點,因此需要按照失配指標跳轉統計。統計過的結點需要特殊標記,避免重複統計,否則會超時。1 include2...
AC自動機模板1 洛谷3808
這是一道簡單的ac自動機模版題。用於檢測正確性以及演算法常數。為了防止卡oj,在保證正確的基礎上只有兩組資料,請不要惡意提交。題目描述 給定n個模式串和1個文字串,求有多少個模式串在文字串裡出現過。第一行乙個n,表示模式串個數 下面n行每行乙個模式串 下面一行乙個文字串。乙個數表示答案 輸入樣例 1...
AC自動機 洛谷P3808 AC自動機(簡單版)
給定 n n 個模式串和1個文字串,求有多少個模式串在文字串裡出現過 多模匹配用ac role presentation aca c自動機 首先建造一棵字典樹,新增所有模式串,然後建造失配指標,最後進行匹配 luogu judger enable o2 include include include...