P3808 【模板】AC自动机(简单版)
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1e6+5; 4 struct Aho_Corasock_Automaton { 5 struct node { 6 int fail; // 失配指针 7 int son[26]; // 子节点的位置 8 int num; // 标记有几个单词以这个节点结尾 9 }Trie[maxn]; 10 int cnt = 0; // Trie指针 11 void insert(char *s) { 12 int len = strlen(s); 13 int now = 0; // Trie当前指针 14 for (int i = 0; i < len; ++i) { 15 if (Trie[now].son[s[i]-'a'] == 0) { // 如果没有这个子节点 16 Trie[now].son[s[i]-'a'] = ++cnt; // 构造该节点 17 } 18 now = Trie[now].son[s[i]-'a']; 19 } 20 Trie[now].num += 1; // 标记单词结尾 21 } 22 void get_fail() { // 构造fail指针 23 queue<int> que; 24 for (int i = 0; i < 26; ++i) { // 先提前构造第二层 25 if (Trie[0].son[i] != 0) { // 如果存在该节点 26 Trie[Trie[0].son[i]].fail = 0; // fail指向root节点 27 que.push(Trie[0].son[i]); // 加入队列 28 } 29 } 30 while (!que.empty()) { // bfs求fail指针 31 int u = que.front(); que.pop(); 32 for (int i = 0; i < 26; ++i) { 33 if (Trie[u].son[i] != 0) { // 如果存在该子节点 34 // 子节点的fail指针指向当前节点的fail指针指向内容相同的子节点 35 Trie[Trie[u].son[i]].fail = Trie[Trie[u].fail].son[i]; 36 que.push(Trie[u].son[i]); // 加入队列 37 } 38 else { // 如果不存在这个子节点 39 // 当前节点的该子节点指向当前节点的fail指针指向的止隔子节点 40 Trie[u].son[i] = Trie[Trie[u].fail].son[i]; 41 } 42 } 43 } 44 } 45 int query(char *s) { // 匹配共有几个模式串出现过 46 int len = strlen(s); 47 int now = 0, ans = 0; // Trie当前的指针,答案ans 48 for (int i = 0; i < len; ++i) { 49 now = Trie[now].son[s[i]-'a']; 50 for (int t = now; t != 0 && Trie[now].num != -1; t = Trie[t].fail) { 51 ans += Trie[t].num; 52 Trie[t].num = -1; // 标记该节点已经匹配过 53 } 54 } 55 return ans; 56 } 57 }AC; 58 char t[maxn], s[maxn]; 59 int main() { 60 int n; scanf("%d",&n); 61 for (int i = 1; i <= n; ++i) { 62 scanf("%s",t); 63 AC.insert(t); 64 } 65 AC.get_fail(); 66 scanf("%s",s); 67 int ans = AC.query(s); 68 printf("%d\n",ans); 69 return 0; 70 }

浙公网安备 33010602011771号