[HDU3065]病毒持续侵袭中(AC自动机)

传送门

AC自动机的又一模板,统计每个字符串在文本中的次数。

所以就不需要vis数组了。

——代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 
 5 using namespace std;
 6 
 7 int n, sz;
 8 int ch[50001][130], val[50001], fail[50001], ans[50001];
 9 char s[2000001], a[1001][50];
10 
11 inline void insert(int k)
12 {
13     int i, x, now = 0, len = strlen(a[k]);
14     for(i = 0; i < len; i++)
15     {
16         x = a[k][i];
17         if(!ch[now][x]) ch[now][x] = ++sz;
18         now = ch[now][x];
19     }
20     val[now] = k;
21 }
22 
23 inline void make_fail()
24 {
25     int i, now = 0;
26     queue <int> q;
27     for(i = 0; i <= 128; i++)
28      if(ch[0][i])
29       q.push(ch[0][i]);
30     while(!q.empty())
31     {
32         now = q.front(), q.pop();
33         for(i = 0; i <= 128; i++)
34         {
35             if(!ch[now][i])
36             {
37                 ch[now][i] = ch[fail[now]][i];
38                 continue;
39             }
40             fail[ch[now][i]] = ch[fail[now]][i];
41             q.push(ch[now][i]);
42         }
43     }
44 }
45 
46 inline void ac()
47 {
48     int i, x, y, now = 0, len = strlen(s);
49     for(i = 0; i < len; i++)
50     {
51         x = s[i];
52         y = ch[now][x];
53         while(y)
54         {
55             ans[val[y]]++;
56             y = fail[y];
57         }
58         now = ch[now][x];
59     }
60 }
61 
62 int main()
63 {
64     int i;
65     while(~scanf("%d", &n))
66     {
67         sz = 0;
68         memset(ch, 0, sizeof(ch));
69         memset(val, 0, sizeof(val));
70         memset(ans, 0, sizeof(ans));
71         memset(fail, 0, sizeof(fail));
72         for(i = 1; i <= n; i++)
73         {
74             scanf("%s", a[i]);
75             insert(i);
76         }
77         make_fail();
78         scanf("%s", s);
79         ac();
80         for(i = 1; i <= n; i++)
81           if(ans[i])
82             printf("%s: %d
", a[i], ans[i]);
83     }
84     return 0;
85 }
View Code
原文地址:https://www.cnblogs.com/zhenghaotian/p/6753764.html