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

     [POI2000]病毒

    题目描述

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

    示例:

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

    任务:

    请写一个程序:

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

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

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


    solution

    首先我们可以建出AC自动机

    我们如果我们可以在ac自动机上找到一个环,且环上没有标记,那么我们就可以一直沿着它走了。

    用dfs找环就可以了。

    要注意一个,如果有一个点的fail被标记了,那么这个点也是不合法的(从根走到它一定会经过标记点)

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define maxn 30005
    using namespace std;
    int n,tr[maxn][2],cnt,e[maxn],fail[maxn];
    char ch[maxn];
    bool vis[maxn],ins[maxn],fsy;
    void inst(){
        int len=strlen(ch),p=0;
        for(int i=0;i<len;i++){
            if(!tr[p][ch[i]-'0'])tr[p][ch[i]-'0']=++cnt;
            p=tr[p][ch[i]-'0'];
        }
        e[p]=1;
    }
    void build(){
        queue<int>q;
        for(int j=0;j<2;j++)if(tr[0][j])q.push(tr[0][j]);
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=0;i<2;i++){
                if(tr[x][i]){
                    fail[tr[x][i]]=tr[fail[x]][i];
                    e[tr[x][i]]|=e[fail[tr[x][i]]];
                    q.push(tr[x][i]);
                }
                else tr[x][i]=tr[fail[x]][i];
            }
        }
    }
    
    void dfs(int x){
        for(int i=0;i<2;i++){
            if(!e[tr[x][i]]){
                if(vis[tr[x][i]]){
                    if(ins[tr[x][i]]){fsy=1;return;}
                }
                else {
                    ins[tr[x][i]]=1;vis[x]=1;
                    dfs(tr[x][i]);
                    ins[tr[x][i]]=0;
                }
            }
        }
        
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf("%s",&ch);inst();
        }
        build();
        dfs(0);
        if(fsy)puts("TAK");
        else puts("NIE");
        return 0;
    }
    
  • 相关阅读:
    [MySQL] MySQL连接字符串总结[转]
    JavaScript删除字符串中的空格
    日期正则表达式[转]
    WIN7拥有管理员权限的使用方法
    SQLWave. GUI Client for MySQL Database Server
    Windows下MySQL多实例运行[转]
    Facebook 的 PHP 性能与扩展性[转]
    改变Datalist行背景色
    Excel导入数据库
    c#创建Table
  • 原文地址:https://www.cnblogs.com/liankewei/p/10358752.html
Copyright © 2011-2022 走看看