您的位置:首页 > 其它

luogu P3796【模板】AC自动机(加强版)

2018-10-10 19:32 531 查看

嘟嘟嘟

 

这个和某谷的AC自动机模板简单版差不多。

但还是要注意几点的:

1.这个是统计出现次数,而不是是否出现,所以在查询的时候加上这个节点的val后,不能把val标记为-1。那么也就可以说查询的时间复杂度能比简单版的稍微第一慢一点。

2.考虑k个一样的模式串:刚开始我想的是每一个节点开一个vector,记录这里是第几个模式串。但其实没有这个必要,对于相同的模式串,我们只用记录任意一个就行,反而在出现次数上要都加上。因为如果主串中存在这些相同的模式串,那么出现次数应该是出现次数 * k。输出的时候如果是这些串最多,那么都应该把这些输出。

1 #include<cstdio>
2 #include<iostream>
3 #include<algorithm>
4 #include<cmath>
5 #include<cstring>
6 #include<cstdlib>
7 #include<cctype>
8 #include<stack>
9 #include<queue>
10 #include<vector>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 1e6 + 5;
21 const int maxm = 1.05e4 + 5;
22 inline ll read()
23 {
24   ll ans = 0;
25   char ch = getchar(), las = ' ';
26   while(!isdigit(ch)) las = ch, ch = getchar();
27   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
28   if(las == '-') ans = -ans;
29   return ans;
30 }
31 inline void write(ll x)
32 {
33   if(x < 0) putchar('-'), x = -x;
34   if(x >= 10) write(x / 10);
35   putchar(x % 10 + '0');
36 }
37
38 int n;
39 char s[maxn], ss[155][75];
40
41 int sum[155];
42 int ch[maxm][26], val[maxm], pos[maxm], f[maxm], cnt = 0;
43 int getnum(char c)
44 {
45   return c - 'a';
46 }
47 void insert(int id, char *s)
48 {
49   int m = strlen(s);
50   int now = 0;
51   for(int i = 0; i < m; ++i)
52     {
53       int c = getnum(s[i]);
54       if(!ch[now][c]) ch[now][c] = ++cnt;
55       now = ch[now][c];
56     }
57   val[now]++; pos[now] = id;
58 }
59 void build()
60 {
61   queue<int> q;
62   for(int i = 0; i < 26; ++i) if(ch[0][i]) q.push(ch[0][i]);
63   while(!q.empty())
64     {
65       int now = q.front(); q.pop();
66       for(int i = 0; i < 26; ++i)
67     {
68       if(ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]);
69       else ch[now][i] = ch[f[now]][i];
70     }
71     }
72 }
73 void query(char *s)
74 {
75   int m = strlen(s), now = 0;
76   for(int i = 0; i < m; ++i)
77     {
78       int c = getnum(s[i]);
79       now = ch[now][c];
80       for(int j = now; j; j = f[j]) sum[pos[j]] += val[j];
81     }
82 }
83
84 void init()
85 {
86   Mem(ch, 0); Mem(val, 0); Mem(pos, 0); Mem(f, 0);
87   Mem(sum, 0);
88   cnt = 0;
89 }
90
91 int main()
92 {
93   while(scanf("%d", &n) && n)
94     {
95       init();
96       for(int i = 1; i <= n; ++i)
97     {
98       scanf("%s", ss[i]);
99       insert(i, ss[i]);
100     }
101       build();
102       scanf("%s", s);
103       query(s);
104       int Max = -1;
105       for(int i = 1; i <= n; ++i) Max = max(Max, sum[i]);
106       write(Max); enter;
107       for(int i = 1; i <= n; ++i) if(sum[i] == Max) printf("%s\n", ss[i]);
108     }
109   return 0;
110 }
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: