P2444 [POI2000]病毒(AC自动机)

https://www.luogu.com.cn/problem/P2444

直接AC自动机即可。
建完后,跑一边AC机,看一下能不能跑出一个不经过病毒,并且循环的字符串。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 const int maxn = 3e4 + 5;
 5 int n;
 6 char s[maxn];
 7 int cnt;
 8 struct node {
 9     int fail, flag, son[2] = {-1,-1};
10 } tree[maxn];
11 
12 queue<int> q;
13 int hh[maxn];
14 bool v[maxn];
15 
16 void insert(char *s) {
17     int u = 0, len = strlen(s + 1);
18     for (int i = 1; i <= len; i++) {
19         int  v = s[i] - '0';
20         if (tree[u].son[v] == -1)
21             tree[u].son[v] = ++cnt;
22         u = tree[u].son[v];
23     }
24     tree[u].flag = 1;
25 }
26 
27 void getfail() {
28     q.push(0);
29     while (!q.empty()) {
30         int u = q.front();
31         q.pop();
32         for (int i = 0; i < 2; i++) {
33             int v = tree[u].son[i];
34             if (v == -1) continue;
35             if (!u) tree[v].fail = 0;
36             else {
37                 int j = tree[u].fail;
38                 while (j && tree[j].son[i] == -1)
39                     j = tree[j].fail;
40                 tree[v].fail = max(tree[j].son[i], 0);
41             }
42             q.push(v);
43         }
44         if (tree[tree[u].fail].flag == 1) tree[u].flag = 1;
45     }
46 }
47 
48 bool dfs(int x) {
49     v[x] = 1;
50     for (int i = 0; i < 2; i++) {
51         int j = x;
52         while (j && tree[j].son[i] == -1) j = tree[j].fail;
53         j = tree[j].son[i];
54         if (j == -1) j = 0;
55         if (v[j]) return 1;
56         if (hh[j] || tree[j].flag == 1) continue;
57         hh[j] = 1;
58         if (dfs(j)) return 1;
59     }
60     v[x] = 0;
61     return 0;
62 }
63 
64 int main() {
65     //freopen("in","r",stdin);
66     scanf("%d",&n);
67     for (int i = 1; i <= n; i++) {
68         scanf("%s", s + 1);
69         insert(s);
70     }
71     getfail();
72     if (dfs(0)) puts("TAK");
73     else puts("NIE");
74     return 0;
75 }
View Code

猜你喜欢

转载自www.cnblogs.com/xcfxcf/p/12534648.html