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 }