• BZOJ 2938: [Poi2000]病毒


    2938: [Poi2000]病毒

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 693  Solved: 360
    [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

    HINT

     

    Source

     
    [Submit][Status][Discuss]

    在AC自动机上找不经过dangerous点的环。

     1 #include <cstdio>
     2 
     3 int tail = 1;
     4 int dang[50005];
     5 int fail[50005];
     6 int next[50005][2];
     7 
     8 inline void insert(char *s)
     9 {
    10     int t = 1; 
    11     
    12     for (; *s; ++s)
    13     {
    14         int c = *s - '0';
    15         
    16         if (next[t][c] == 0)
    17             next[t][c] = ++tail;
    18         
    19         t = next[t][c];
    20     }
    21     
    22     dang[t] = true;    //dangerous node
    23 }
    24 
    25 inline void preworkFail(void)
    26 {
    27     static int que[100005], l, r;
    28     
    29     fail[que[l = 0] = r = 1] = 0;
    30     
    31     while (l != r)
    32     {
    33         int u = que[l++];
    34         
    35         for (int i = 0; i < 2; ++i)
    36         {
    37             if (next[u][i] == 0)
    38                 next[u][i] = next[fail[u]][i];
    39             else
    40             {
    41                 int t = fail[u];
    42                 
    43                 while (next[t][i] == 0)
    44                     t = fail[t];
    45                 
    46                 fail[next[u][i]] = next[t][i];
    47                 
    48                 if (dang[next[t][i]])
    49                     dang[next[u][i]] = true;
    50                 
    51                 que[r++] = next[u][i];
    52             }
    53         }
    54     }
    55 }
    56 
    57 bool vis[50005];
    58 bool ins[50005];
    59 
    60 bool findCircle(int u)
    61 {
    62     ins[u] = true;
    63     
    64     for (int i = 0, v; i < 2; ++i)
    65         if (v = next[u][i])
    66         {
    67             if (ins[v])return true;
    68             if (vis[v] || dang[v])continue;
    69             if (findCircle(v))return true;
    70         }
    71     
    72     vis[u] = true;
    73     ins[u] = false;
    74     
    75     return false;
    76 }
    77 
    78 signed main(void)
    79 {
    80     static int n;
    81     static char str[30005];
    82     
    83     scanf("%d", &n);
    84     
    85     next[0][1] = next[0][0] = 1;
    86     
    87     for (int i = 1; i <= n; ++i)
    88         scanf("%s", str), insert(str);
    89     
    90     preworkFail();
    91     
    92     puts(findCircle(1) ? "TAK" : "NIE");
    93 }

    @Author: YouSiki

  • 相关阅读:
    23.Vue技术栈开发实战-Icon组件
    shell脚本每行后面多了一个^M的原因和解决办法
    mmap概述
    camera otp介绍
    brk实现
    USB技术浅析
    带你遨游USB世界
    echarts 更换主题颜色
    Hive UDAF介绍与开发
    2020湖北高考理科第一名唐楚玥的学习方法演讲
  • 原文地址:https://www.cnblogs.com/yousiki/p/6281959.html
Copyright © 2020-2023  润新知