首页 > 其他 > 详细

【BZOJ2938】[Poi2000]病毒 AC自动机+DFS

时间:2017-01-09 18:14:01      阅读:179      评论:0      收藏:0      [点我收藏+]

【BZOJ2938】[Poi2000]病毒

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合并到儿子节点上,删去单词的结束点,然后用DFS看一下Trie树里有没有环就行了,有环就是TAK

也可以用拓补排序判环,但是比较难搞,因为不知道入度什么时候为0

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int maxn=30010;
struct node
{
    int ch[2],fail,cnt;
}p[maxn];
int n,tot,ans;
char str[maxn];
int vis[maxn],ins[maxn];
queue<int> q;
void dfs(int x)
{
    int i;
    ins[x]=vis[x]=1;
    for(i=0;i<=1;i++)
    {
        if(p[p[x].ch[i]].cnt)    continue;
        if(!vis[p[x].ch[i]])    dfs(p[x].ch[i]);
        else if(ins[p[x].ch[i]])    ans=1;
    }
    ins[x]=0;
}
int main()
{
    scanf("%d",&n);
    int i,j,k,u,t;
    tot=1;
    for(i=1;i<=n;i++)
    {
        scanf("%s",str);
        k=strlen(str);
        u=1;
        for(j=0;j<k;j++)
        {
            if(!p[u].ch[str[j]-0])    p[u].ch[str[j]-0]=++tot;
            u=p[u].ch[str[j]-0];
        }
        p[u].cnt=1;
    }
    q.push(1);
    while(!q.empty())
    {
        u=q.front(),q.pop();
        for(i=0;i<=1;i++)
        {
            if(p[u].ch[i])
            {
                q.push(p[u].ch[i]);
                if(u==1)    p[p[u].ch[i]].fail=1;
                else p[p[u].ch[i]].fail=p[p[u].fail].ch[i];
                p[p[u].ch[i]].cnt|=p[p[p[u].fail].ch[i]].cnt;
            }
            else
            {
                if(u==1)    p[u].ch[i]=1;
                else    p[u].ch[i]=p[p[u].fail].ch[i];
            }
        }
    }
    dfs(1);
    if(ans==1)    printf("TAK");
    else    printf("NIE");
    return 0;
}

 

 

【BZOJ2938】[Poi2000]病毒 AC自动机+DFS

原文:http://www.cnblogs.com/CQzhangyu/p/6265667.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!