• 【bzoj2938】[Poi2000]病毒


    2938: [Poi2000]病毒

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 579  Solved: 304
    [Submit][Status][Discuss]

    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自动机,然后判环即可。
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<ctime>
     6 #include<cmath>
     7 #include<algorithm>
     8 using namespace std;
     9 int n,cnt(1),end[30010],size[30010],q[30010],fail[30010],ins[30010],vis[30010],tr[30010][2];
    10 char ch[30010];
    11 inline int read()
    12 {
    13     int x=0,f=1;  char ch=getchar();
    14     while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
    15     while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
    16     return x*f;
    17 }
    18 void Insert()
    19 {
    20     int now=0,l=strlen(ch+1);
    21     for(int i=1;i<=l;i++)
    22     {
    23         if(!tr[now][ch[i]-'0']) tr[now][ch[i]-'0']=++cnt;
    24         now=tr[now][ch[i]-'0'];
    25     }
    26     end[now]=1;
    27 }
    28 void build()
    29 {
    30     int head=0,tail=0;
    31     for(int i=0;i<=1;i++)  if(tr[0][i])  q[++tail]=tr[0][i];
    32     while(++head<=tail)
    33     {
    34         int x=q[head];
    35         for(int i=0;i<=1;i++)
    36         {    
    37             int y=tr[x][i];
    38             if(!y){tr[x][i]=tr[fail[x]][i];continue;}
    39             q[++tail]=y;
    40             int temp=fail[x];
    41             while(!tr[temp][i]) temp=fail[temp];
    42             fail[y]=tr[temp][i];  
    43             end[y]|=end[tr[temp][i]];
    44         }    
    45     }
    46 }
    47 bool dfs(int x)
    48 {
    49     ins[x]=1;
    50     for(int i=0;i<2;i++)
    51     {
    52         int v=tr[x][i];
    53         if(ins[v])return 1;
    54         if(vis[v]||end[v])continue;
    55         vis[v]=1;
    56         if(dfs(v))return 1;
    57     }
    58     ins[x]=0;
    59     return 0;
    60 }
    61 int main()
    62 {
    63     //freopen("cin.in","r",stdin);
    64     //freopen("cout.out","w",stdout);
    65     n=read();
    66     for(int i=1;i<=n;i++)  {scanf("%s",ch+1);  Insert();}
    67     build();
    68     if(dfs(0))  printf("TAK
    ");
    69     else printf("NIE
    ");
    70     return 0;
    71 }
     
     
  • 相关阅读:
    Python基础学习四 文件操作(二)
    Python基础学习三 文件操作(一)
    Python基础学习三 字符串
    Python基础学习三 字典、元组
    Python基础学习三 list-增删改查、切片、循环、排序
    python基础4文件操作
    Python基础3切片,字符串的方法,for 循环
    python2和Python3的区别(长期更新)
    Python基础1
    python 中的enumerate()函数的用法
  • 原文地址:https://www.cnblogs.com/chty/p/6000085.html
Copyright © 2020-2023  润新知