zoukankan      html  css  js  c++  java
  • 病毒(bzoj 2938)

    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自动机,在不能走每个单词最后一个字母的前提下,如果某个字符串在自动机上无法匹配,
        则说明可以找到无限长的字符串。
        为了方便起见,将所有的point指针合并,最后在自动机上搜索就行了。 
    */
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define N 30010
    using namespace std;
    int a[N][2],point[N],danger[N],ins[N],vis[N],n,size=1;
    char s[N];
    queue<int> q;
    void insert(){
        int len=strlen(s),now=1;
        for(int i=0;i<len;i++){
            int t=s[i]-'0';
            if(!a[now][t]) a[now][t]=++size;
            now=a[now][t];
        }
        danger[now]=1;
    }
    void build(){
        q.push(1);point[1]=0;
        while(!q.empty()){
            int now=q.front();q.pop();
            for(int i=0;i<2;i++){
                if(!a[now][i]){
                    a[now][i]=a[point[now]][i];
                    continue;
                }
                int k=point[now];
                while(!a[k][i]) k=point[k];
                point[a[now][i]]=a[k][i];
                danger[a[now][i]]|=danger[point[a[now][i]]];
                q.push(a[now][i]);
            }
        }
    }
    bool dfs(int x){
        ins[x]=1;
        for(int i=0;i<2;i++){
            if(ins[a[x][i]]) return true;
            if(vis[a[x][i]]||danger[a[x][i]]) continue;
            vis[a[x][i]]=1;
            if(dfs(a[x][i])) return true;
        }
        ins[x]=0;
        return false;
    }
    int main(){
        scanf("%d",&n);
        for(int i=0;i<2;i++) a[0][i]=1;
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            insert();
        }
        build();
        if(dfs(1)) printf("TAK");
        else printf("NIE");
        return 0;
    }
  • 相关阅读:
    C语言-第32课
    typeof和clamp
    C语言void*和*p的使用
    C语言二级指针和一级指针
    C语言结构体变量成员之指针变量成员的坑
    控制硬件三部曲
    C语言const char*使用
    jiffies是什么
    TPO3-1 Architecture
    相关关系|相关系数|线性关系|
  • 原文地址:https://www.cnblogs.com/harden/p/6551055.html
Copyright © 2011-2022 走看看