[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 }