【bzoj2938】【Poi2000】病毒

  • 题解:

    •  对病毒串建立ac自动机;
    • 有一个无限长的串等价于可以一直在自动机上匹配,等价于自动机上的转移有环;
    • 当然前提是去掉病毒节点的fail子树;
    • 写一个dfs记录是否在栈中,来过没有找到就不必再来了再记录一个vis保证复杂度;
    • 然而。。。。。。我在找环的时候呆了很久,最后写了tarjan;
    • 如果你也是有些tarjan的危险想法的话注意特判转移的自环的情况;
  •  1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=30010;
     4 int n,sz,ch[N][2],fl[N],que[N],head,tail,vis[N],hd[N],o,dfn[N],idx,low[N],fg,del[N];
     5 struct Edge{int v,nt;}E[N<<1];
     6 char s[N];
     7 void adde(int u,int v){
     8     if(u==v)fg=1;
     9     E[o]=(Edge){v,hd[u]};hd[u]=o++;
    10 }
    11 void get_fl(){
    12     for(int i=0;i<2;i++)if(ch[0][i]){
    13         que[++tail]=ch[0][i];
    14         if(!vis[ch[0][i]])adde(0,ch[0][i]);
    15     }else {fg=1;return;}
    16     while(head<tail){
    17         int u=que[++head];
    18         for(int i=0;i<2;i++){
    19             int&v=ch[u][i];
    20             if(!v){
    21                 v=ch[fl[u]][i];
    22                 if(!vis[v])adde(u,v);
    23                 continue;
    24             }
    25             fl[v]=ch[fl[u]][i];
    26             vis[v]|=vis[fl[v]];
    27             if(!vis[v])adde(u,v);
    28             que[++tail]=v;
    29         }
    30     }
    31 }
    32 void tarjan(int u){
    33     if(fg)return ;
    34     que[++head]=u;
    35     dfn[u]=low[u]=++idx;
    36     for(int i=hd[u];~i;i=E[i].nt){
    37         int v=E[i].v;
    38         if(!dfn[v])tarjan(v),low[u]=min(low[u],low[v]);
    39         else if(!del[v])low[u]=min(low[u],dfn[v]);
    40     }
    41     if(dfn[u]==low[u]){
    42         int cnt=0,v;
    43         do{
    44             cnt++;
    45             del[v=que[head--]]=1;
    46         }while(v!=u);
    47         if(cnt > 1)fg=1;
    48     }
    49 }
    50 int main(){
    51 //    freopen("bzoj2938.in","r",stdin);
    52 //    freopen("bzoj2938.out","w",stdout);
    53     memset(hd,-1,sizeof(hd));
    54     scanf("%d",&n);
    55     for(int i=1;i<=n;i++){
    56         scanf("%s",s+1);
    57         int len=strlen(s+1),u=0;
    58         for(int j=1;j<=len;j++){
    59             if(!ch[u][s[j]-'0'])ch[u][s[j]-'0']=++sz;
    60             u=ch[u][s[j]-'0'];
    61         }
    62         vis[u]=1;
    63     }
    64     get_fl();
    65     head=0;tarjan(0);
    66     if(fg)puts("TAK");else puts("NIE");
    67     return 0;
    68 }
    bzoj2938

     

posted @ 2019-01-06 21:02  大米饼  阅读(143)  评论(0编辑  收藏  举报