bzoj 2938 [Poi2000]病毒 AC自动机

 [Poi2000]病毒

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 1319  Solved: 659
[Submit][Status][Discuss]

Description

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
l         读入病毒代码;
l         判断是否存在一个无限长的安全代码;
l         将结果输出

Input

 
第一行包括一个整数n,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

Output

你应在在文本文件WIN.OUT的第一行输出一个单词:
l         TAK——假如存在这样的代码;
l         NIE——如果不存在。

Sample Input

3
01
11
00000

Sample Output

NIE

题解:

首先我们把所有串建一个AC自动机

方便起见我们直接把fail指针合并到子结点

如果一个串能无限长,也就是说它可以在AC自动机上一直进行匹配但就是匹配不上

也就是说匹配指针不能走到val为1的结点,设这个点为x

即root..x是一个病毒串

那么fail指针指向x的y也不能走

因为root..x是root..y的一个后缀

处理出来判断有向图是否有环

 1 #include<cstring>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdio>
 6 #include<queue>
 7 
 8 #define N 30007
 9 using namespace std;
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
14     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 int n,m,cnt=1;
19 bool flag[N],ans,ins[N];
20 struct Node
21 {
22     int c[2],suf;
23     bool flag;
24 }trie[N];
25 char ch[N];
26 
27 void insert()
28 {
29     int now=1,len=strlen(ch);
30     for (int i=0;i<len;i++)
31     {
32         if (!trie[now].c[ch[i]-'0']) trie[now].c[ch[i]-'0']=++cnt;
33         now=trie[now].c[ch[i]-'0'];
34     }
35     trie[now].flag=true;
36 }
37 void make_AC()
38 {
39     for (int i=0;i<2;i++)
40         trie[0].c[i]=1;
41     queue<int>q;while(!q.empty()) q.pop();
42     trie[1].suf=0;
43     q.push(1);
44     while(!q.empty())
45     {
46         int u=q.front();q.pop();
47         for (int i=0;i<2;i++)
48             if (trie[u].c[i])
49             {
50                 trie[trie[u].c[i]].suf=trie[trie[u].suf].c[i];
51                 if (trie[trie[trie[u].c[i]].suf].flag) trie[trie[u].c[i]].flag=true;
52                 q.push(trie[u].c[i]);
53             }
54             else trie[u].c[i]=trie[trie[u].suf].c[i];
55     }
56 }
57 void dfs(int u)
58 {
59     ins[u]=true;
60     for (int i=0;i<2;i++)
61     {
62         int v=trie[u].c[i];
63         if (ins[v]) ans=true;
64         if (trie[v].flag||flag[v]) continue;
65         flag[v]=true;
66         dfs(v);
67     }
68     ins[u]=false;
69 }
70 int main()
71 {
72     n=read();
73     for (int i=1;i<=n;i++)
74     {
75         scanf("%s",ch);
76         insert();
77     }
78     make_AC(),dfs(1);
79     if (ans) printf("TAK
");
80     else printf("NIE
");
81 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8847776.html