[POI2000]病毒 - AC自动机

          [POI2000]病毒

题目描述

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

示例:

例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。

任务:

请写一个程序:

1.在文本文件WIR.IN中读入病毒代码;

2.判断是否存在一个无限长的安全代码;

3.将结果输出到文件WIR.OUT中。

输入输出格式

输入格式:

在文本文件WIR.IN的第一行包括一个整数n(n\le 2000)(n2000) ,表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

输出格式:

在文本文件WIR.OUT的第一行输出一个单词:

TAK——假如存在这样的代码;

NIE——如果不存在。

输入输出样例

输入样例#1:
3
01 
11 
00000
输出样例#1:
NIE

根据给出的病毒建出AC自动机,在上面DFS找环,单词的结尾的节点不能走,有环就代表有解。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <queue>
  5 #include <algorithm>
  6 #define LL long long
  7 
  8 using namespace std;
  9 
 10 queue<int> q;
 11 int len;
 12 const int MAXN = 2e3 + 10;
 13 char s[MAXN];
 14 int vis[MAXN], instack[MAXN];
 15 int flag = 0;
 16 struct trie {
 17     int fail;
 18     int vis[2];
 19     int judge;
 20 } t[MAXN * 10];
 21 
 22 inline LL read()
 23 {
 24     LL x = 0, w = 1; char ch = 0;
 25     while(ch < '0' || ch > '9') {
 26         if(ch == '-') {
 27             w = -1;
 28         }
 29         ch = getchar();
 30     }
 31     while(ch >= '0' && ch <= '9') {
 32         x = x * 10 + ch - '0';
 33         ch = getchar();    
 34     }
 35     return x * w;
 36 }
 37 int tot = 0;
 38 
 39 void insert()
 40 {
 41     int x = 0;
 42     for(int i = 1; i <= len; i++) {
 43         if(t[x].vis[s[i] - '0'] == 0) {
 44             t[x].vis[s[i] - '0'] = ++tot;
 45         }
 46         x = t[x].vis[s[i] - '0'];
 47     }
 48     t[x].judge = 1;
 49 }
 50 
 51 void getfail()
 52 {
 53     for(int i = 0; i < 2; i++) {
 54         if(t[0].vis[i]) {
 55             t[t[0].vis[i]].fail = 0;
 56             q.push(t[0].vis[i]);        
 57         }
 58     }
 59     while(!q.empty()) {
 60         int x = q.front();
 61         q.pop();
 62         for(int i = 0; i < 2; i++) {
 63             if(!t[x].vis[i]) {
 64                 t[x].vis[i] = t[t[x].fail].vis[i];
 65             } else { 
 66                 t[t[x].vis[i]].fail = t[t[x].fail].vis[i];
 67                 if(t[t[t[x].vis[i]].fail].judge == 1) {
 68                     t[t[x].vis[i]].judge = 1;
 69                 }
 70                 q.push(t[x].vis[i]);
 71             }
 72         }
 73     }
 74 }
 75 
 76 void DFS(int x)
 77 {
 78     instack[x]++;
 79     if(flag || t[x].judge == 1) {
 80         return;
 81     }
 82     vis[x] = 1;
 83     for(int i = 0; i < 2; i++) {
 84         if(vis[t[x].vis[i]] == 1 && instack[t[x].vis[i]]) {
 85             //cout<<t[x].vis[i]<<endl;
 86             flag = 1;
 87             return;
 88         }
 89         if(!vis[t[x].vis[i]]) {
 90             DFS(t[x].vis[i]);
 91         }
 92     }
 93     instack[x]--;
 94 }
 95 
 96 int main()
 97 {
 98     int n;
 99     n = read();
100     for(int i = 1; i <= n; i++) {
101         scanf("%s", s + 1);
102         len = strlen(s + 1);
103         insert();
104     }
105     getfail();
106     flag = 0;
107     DFS(0);
108     if(flag) {
109         cout<<"TAK"<<endl;
110     } else {
111         cout<<"NIE"<<endl;
112     }
113 }
114  
View Code

 

posted @ 2018-03-27 19:35  大财主  阅读(178)  评论(0编辑  收藏  举报