[Poi2000] 病毒

2938: [Poi2000]病毒

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 1633  Solved: 835
[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

HINT

 

题意:

给你$n$个01串,问是否存在一个无限长的串使得这$n$个串都不是它的子串。

 

题解:

建立$AC$自动机,那么若满足题意当且仅当在$AC$自动机上存在一个环不经过任意一个$end$节点,$dfs$找环即可。

找环时注意:(对所有图论问题均有)

  • 存在环的条件不仅是$u\rightarrow v$中的$v$被遍历过,它还要在当前遍历序列中!(主要是我又一次忘了把$vis_u$标记清0)
  • 若当前$u$的出边被遍历完并且没有找到环,说明$u$一定不在任何一个环上(反证),所以可以直接把它$delete$掉。

 

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;
#define MAXN 100005
#define MAXM 500005
#define ll long long

struct node{
    int son[2];
    bool ise,vis,ok;
}tree[MAXN];
int tot=1,nxt[MAXN];
bool flag;char str[MAXN];
inline int read(){
    int x=0,f=1;
    char c=getchar();
    for(;!isdigit(c);c=getchar())
        if(c=='-')
            f=-1;
    for(;isdigit(c);c=getchar())
        x=x*10+c-'0';
    return x*f;
}

inline void add(char *str){
    int N=strlen(str),u=1;
    for(int i=0;i<N;i++){
        int ch=str[i]-'0';
        if(!tree[u].son[ch]) 
            tree[u].son[ch]=++tot;
        u=tree[u].son[ch];
    }
    tree[u].ise=1;
    return;    
}

inline void get_nxt(){
    for(int i=0;i<2;i++)
        tree[0].son[i]=1;
    queue<int> q; q.push(1);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=0;i<2;i++){
            if(tree[u].son[i]){
                q.push(tree[u].son[i]);
                nxt[tree[u].son[i]]=tree[nxt[u]].son[i];
                tree[tree[u].son[i]].ise|=tree[nxt[tree[u].son[i]]].ise;
            }
            else tree[u].son[i]=tree[nxt[u]].son[i];
        }
    }
    return;
}

inline int dfs(int u){
    tree[u].vis=tree[u].ok=1;
    for(int i=0;i<2;i++){
        int v=tree[u].son[i];
        if(tree[v].vis || (!tree[v].ok && !tree[v].ise && dfs(v)))
            return 1;
    }
    tree[u].vis=0;
    return 0;
}

int main(){
    int N=read();
    for(int i=1;i<=N;i++)
        scanf("%s",str),add(str);
    get_nxt();
    if(dfs(1)) printf("TAK\n");
    else printf("NIE\n");
     return 0;
}

 

posted @ 2018-10-23 20:36  Fugtemypt  阅读(138)  评论(0编辑  收藏  举报