【AC自动机】病毒

【题目链接】

https://loj.ac/problem/10062

 

【题意】

寻找一个没有模式串为子串的无限01串。是否存在。

 

【题解】

其实就是用dfs找一个环。

1、环需要从根结点出发找到这个位置。且重新能走到这里,我们开一个“预测路径”的数组进行标记即可。

2、如果下一个结点碰上了“走过”标记过的,而不是“预测路径”,或者是模式串结尾,我们就避开不走。

 

注意:

fail数组是可以进行传递的,就是说fail指向的结点,同时是模式串的结尾,那么该位置也是不合法的。

 

最后看看代码怎么实现就明白了。

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 
 5 using namespace std;
 6 
 7 const int N = 2005;
 8 const int M = 30005;
 9 
10 int Trie[M][2] , fail[M] , End[M], idx ;
11 int Q[M] , Head , Tail ;
12 int vis[M],used[M];
13 int n ;
14 
15 char str[N];
16 
17 void Insert( char s[] ){
18     int p = 0;
19     for(int i=0 ; s[i] ; i++ ){
20         int t = s[i] - '0' ;
21         if( !Trie[p][t] )
22             Trie[p][t] = ++idx ;
23         p = Trie[p][t];
24     }
25     End[p] ++ ;
26 }
27 
28 void Build(){
29     Head = 1 , Tail = 0 ;
30     for(int i=0;i<2;i++)
31         if(Trie[0][i])
32             Q[++Tail] = Trie[0][i] ;
33         //fail[Trie[0][i]] = 0;
34 
35     while( Head <= Tail ){
36         int u = Q[Head++] ;
37         for(int i=0;i<2;i++){
38             int To = Trie[u][i];
39             if( To ){
40                 fail[To] = Trie[fail[u]][i];
41                 Q[++Tail] = To;
42 
43                 End[To] = End[To] || End[fail[To]] ;
44             }else{
45                 Trie[u][i] = Trie[fail[u]][i];
46             }
47         }
48     }
49 
50 }
51 
52 bool dfs(int u){
53     vis[u] = 1;
54     for(int i=0;i<=1;i++){
55         int To = Trie[u][i];
56         if( vis[To] ) return true;
57         if( used[To] || End[To] ) continue;
58         used[To] = 1 ;
59         if( dfs(To) ) return true ;
60     }
61     vis[u] = 0;
62     return false ;
63 }
64 int main()
65 {
66     scanf("%d",&n);
67     for(int i=0;i<n;i++){
68         scanf("%s",str);
69         Insert(str);
70     }
71     Build();
72     puts(dfs(0)?"TAK":"NIE");
73 
74     return 0 ;
75 }
病毒

 

posted @ 2019-08-17 00:36  Osea  阅读(214)  评论(0编辑  收藏  举报