• 【BZOJ】【2938】【POI2000】病毒


    AC自动机


      好题>_<(其实是一次AC有些感动)

      嗯要找到无限长的一个字符串不包含任何一个模板串,就意味着在AC自动机(Trie图)上找到一个不经过任何一个危险结点的环,深搜一下就好了……记得离开某个结点的时候要清除标记!有点像tarjan……

     1 /**************************************************************
     2     Problem: 2938
     3     User: Tunix
     4     Language: C++
     5     Result: Accepted
     6     Time:68 ms
     7     Memory:3528 kb
     8 ****************************************************************/
     9  
    10 //BZOJ 2938
    11 #include<vector>
    12 #include<cstdio>
    13 #include<cstring>
    14 #include<cstdlib>
    15 #include<iostream>
    16 #include<algorithm>
    17 #define rep(i,n) for(int i=0;i<n;++i)
    18 #define F(i,j,n) for(int i=j;i<=n;++i)
    19 #define D(i,j,n) for(int i=j;i>=n;--i)
    20 #define pb push_back
    21 using namespace std;
    22 inline int getint(){
    23     int v=0,sign=1; char ch=getchar();
    24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
    25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
    26     return v*sign;
    27 }
    28 const int N=1e5+10,INF=~0u>>2;
    29 typedef long long LL;
    30 /******************tamplate*********************/
    31 struct Trie{
    32     int ch[2],fail;
    33     bool sign;
    34 }T[N];
    35 char s1[N];
    36 int cnt=1,Q[N];
    37 void ins(){
    38     scanf("%s",s1);
    39     int x=1,y;
    40     rep(i,strlen(s1)){
    41         y=s1[i]-'0';
    42         if (!T[x].ch[y]) T[x].ch[y]=++cnt;
    43         x=T[x].ch[y];
    44     }
    45     T[x].sign=1;
    46 }
    47 void make_fail(){
    48     int l=0,r=-1;
    49     Q[++r]=1;
    50     while(l<=r){
    51         int x=Q[l++],y,j;
    52         T[x].sign|=T[T[x].fail].sign;
    53         rep(i,2){
    54             j=T[x].fail;
    55             while(j && T[j].ch[i]==0) j=T[j].fail;
    56             if (T[x].ch[i]){
    57                 y=T[x].ch[i];
    58                 T[y].fail=j ? T[j].ch[i] : 1;
    59                 Q[++r]=y;
    60             }else T[x].ch[i]=j ? T[j].ch[i] : 1;
    61         }
    62     }
    63 }
    64 bool vis[N],in[N];
    65 bool dfs(int x){
    66     if (vis[x]) return 0;
    67     bool ans=0;
    68     if (T[x].sign) return 0;
    69     vis[x]=in[x]=1;
    70     rep(i,2){
    71         if (in[T[x].ch[i]]) return 1;
    72         if (!T[T[x].ch[i]].sign) ans|=dfs(T[x].ch[i]);
    73     }
    74     in[x]=0;
    75     return ans;
    76 }
    77 int main(){
    78 #ifndef ONLINE_JUDGE
    79     freopen("2938.in","r",stdin);
    80     freopen("2938.out","w",stdout);
    81 #endif
    82     int n=getint();
    83     F(i,1,n) ins();
    84     make_fail();
    85     if (dfs(1)) puts("TAK");
    86     else puts("NIE");
    87     return 0;
    88 }
    View Code

    2938: [Poi2000]病毒

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 155  Solved: 87
    [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]
  • 相关阅读:
    spring MVC fromeWork 與webwork2 mvc 比較
    JAVA Oauth 认证服务器的搭建
    HTTPS的工作原理
    理解HTTP幂等性
    支付交易一般性准则
    设计模式六大原则
    腾讯微信技术总监周颢:一亿用户增长背后的架构秘密
    Valid Parentheses
    4Sum
    Letter Combinations of a Phone Number
  • 原文地址:https://www.cnblogs.com/Tunix/p/4396559.html
Copyright © 2020-2023  润新知