1. 程式人生 > >2938: [Poi2000]病毒

2938: [Poi2000]病毒

ring lse 無限 urn pac 安全 程序 pre cst

Description

二進制病毒審查委員會最近發現了如下的規律:某些確定的二進制串是病毒的代碼。如果某段代碼中不存在任何一段病毒代碼,那麽我們就稱這段代碼是安全的。現在委員會已經找出了所有的病毒代碼段,試問,是否存在一個無限長的安全的二進制代碼。

示例:

例如如果{011, 11, 00000}為病毒代碼段,那麽一個可能的無限長安全代碼就是010101…。如果{01, 11, 000000}為病毒代碼段,那麽就不存在一個無限長的安全代碼。

任務:

請寫一個程序:

l 讀入病毒代碼;

l 判斷是否存在一個無限長的安全代碼;

l 將結果輸出


只要trie圖上有一個能從0到達且沒有結束標記的環,我們就可以在那個環上繞啊繞啊繞啊


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define M 800001
using namespace std;

int n,m,k,cnt,d[M][2],a[M],fail[M],e[M];
char c[M];
bool b[M],bl[M];
queue<int>q;
void ins(char* s)
{
    int l=strlen(s), now=0; 
    for(int i=0;i<l;i++) 
    {
        if(!d[now][s[i]-'0']) d[now][s[i]-'0']=++cnt;
        now=d[now][s[i]-'0'];
    }
    e[now]=1;
}

void built()
{
    if(d[0][0]) q.push(d[0][0]);
    if(d[0][1]) q.push(d[0][1]);
    while(q.size())
    {
        int x=q.front(); q.pop();
        if(e[fail[x]]) e[x]=1;
        if(d[x][0])fail[d[x][0]]=d[fail[x]][0], q.push(d[x][0]);
        else d[x][0]=d[fail[x]][0];
        if(d[x][1]) fail[d[x][1]]=d[fail[x]][1], q.push(d[x][1]);
        else d[x][1]=d[fail[x]][1];
    }
}

bool bfs(int x)
{
    if(e[x]) return 0;
    if(bl[x]) return 1;
    if(b[x]) return 0;
    bl[x]=b[x]=1;
    if(bfs(d[x][0])) return 1;
    if(bfs(d[x][1])) return 1;
    bl[x]=0;
    return 0;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%s",c), ins(c);
    built();
    if(bfs(0)) printf("TAK");
    else printf("NIE");
}

2938: [Poi2000]病毒