zoukankan      html  css  js  c++  java
  • P2444 [POI2000]病毒

    题目描述

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

    示例:

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

    任务:

    请写一个程序:

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

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

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

    输入输出格式

    输入格式:

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

    输出格式:

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

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

    NIE——如果不存在。

    输入输出样例

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

    Solution:

       本题AC自动机+dfs。

      直接对n个串构建出AC自动机,在求fail时,顺带把会出现单词作为后缀的节点标记,直接用失配边的end值更新当前节点就好了,然后从根节点跑一遍dfs,每次都不走那些被标记的节点或者已经搜索过肯定无解的节点,那么只要搜到了环,就说明可行。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=30005;
    int trie[N][2],cnt,fail[N],n;
    bool ed[N],vis[N],ct[N];
    char s[N];
    
    il void insert(char *s){
        int len=strlen(s),p=0,x;
        For(i,0,len-1){
            x=s[i]-'0';
            if(!trie[p][x])trie[p][x]=++cnt;
            p=trie[p][x];
        }
        ed[p]=1;
    }
    
    il void bfs(){
        queue<int>q;
        For(i,0,1) if(trie[0][i]) q.push(trie[0][i]);
        while(!q.empty()){
            int u=q.front();q.pop();
            For(i,0,1){
                int &v=trie[u][i];
                if(v) fail[v]=trie[fail[u]][i],ed[v]|=ed[fail[v]],q.push(v);
                else v=trie[fail[u]][i];
            }
        }
    }
    
    il void dfs(int now){
        if(vis[now]) puts("TAK"),exit(0);
        if(ct[now]||ed[now])return;
        vis[now]=ct[now]=1;
        dfs(trie[now][0]),dfs(trie[now][1]);
        vis[now]=0;
    }
    
    il void init(){
        scanf("%d",&n);
        For(i,1,n) scanf("%s",s),insert(s);
        bfs();
        dfs(0);
        puts("NIE");
    }
    
    int main(){
        init();
        return 0;
    }
  • 相关阅读:
    php大力力 [048节] php一点支付开发资料,很散
    php大力力 [047节] 寻找程序员的方法和应用
    ECharts的简单使用
    xlsxwriter新建Excel文件-制图
    xlsxwriter新建Excel文件
    xlrd读取Excel文件
    抽奖概率互斥算法
    Redis 的 8 大数据类型!
    Django Web框架入门-博客(更新完成)
    Git学习
  • 原文地址:https://www.cnblogs.com/five20/p/9473479.html
Copyright © 2011-2022 走看看