P3808 【模板】AC自动机(简单版)

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 }

 

posted @ 2019-10-20 21:58  麻辣猪仔  阅读(138)  评论(0)    收藏  举报