• 病毒(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;
    }
  • 相关阅读:
    OSG绘制几何图形
    OSGMFC
    OSG第一个Demo
    线性四叉树十进制Morton码计算示例
    单源最短路径——Dijkstra算法学习
    .Net内存优化的几点经验
    强制回收和IDisposable.Dispose方法
    七参数计算正确性验证——Coord软件使用
    [转载]windows任务管理器中的工作设置内存,内存专用工作集,提交大小详解
    T4自动生成数据库C#实体类学习(1)
  • 原文地址:https://www.cnblogs.com/harden/p/6551055.html
Copyright © 2020-2023  润新知