[POI2000]病毒

题目大意:
  给定$n$个字符串$s_i(sum|s_i|leq30000)$,问是否能够造出一个无限长的字符串$t$,使得$t$中没有任何一个$s_i$。

思路:
  构造AC自动机。在自动机上DFS,避开所有的危险结点,判断是否有环。若存在环,则$t$存在。

 1 #include<queue>
 2 #include<cstdio>
 3 #include<cctype>
 4 inline int getint() {
 5     register char ch;
 6     while(!isdigit(ch=getchar()));
 7     register int x=ch^'0';
 8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
 9     return x;
10 }
11 const int N=30001,S=2;
12 char s[N];
13 class AhoCorasick {
14     private:
15         int ch[N][S],fail[N];
16         bool dan[N],ins[N],vis[N];
17         std::queue<int> q;
18         int sz,new_node() {
19             return ++sz;
20         }
21         int idx(const int &c) const {
22             return c^'0';
23         }
24     public:
25         void insert(const char s[]) {
26             int p=0;
27             for(register int i=0;s[i];i++) {
28                 const int c=idx(s[i]);
29                 p=ch[p][c]?:ch[p][c]=new_node();
30             }
31             dan[p]=true;
32         }
33         void get_fail() {
34             for(register int c=0;c<S;c++) {
35                 if(ch[0][c]) q.push(ch[0][c]);
36             }
37             while(!q.empty()) {
38                 const int &x=q.front();
39                 for(register int c=0;c<S;c++) {
40                     int &y=ch[x][c];
41                     if(!y) {
42                         y=ch[fail[x]][c];
43                         continue;
44                     }
45                     fail[y]=ch[fail[x]][c];
46                     dan[y]|=dan[fail[y]];
47                     q.push(y);
48                 }
49                 q.pop();
50             }
51         }
52         bool dfs(const int &x) {
53             ins[x]=vis[x]=true;
54             for(int c=0;c<S;c++) {
55                 const int &y=ch[x][c];
56                 if(ins[y]) return true;
57                 if(dan[y]||vis[y]) continue;
58                 if(dfs(y)) return true;
59             }
60             return ins[x]=false;
61         }
62 };
63 AhoCorasick ac;
64 int main() {
65     for(register int i=getint();i;i--) {
66         scanf("%s",s);
67         ac.insert(s);
68     }
69     ac.get_fail();
70     puts(ac.dfs(0)?"TAK":"NIE");
71     return 0;
72 }
原文地址:https://www.cnblogs.com/skylee03/p/8571547.html