P2444 [POI2000]病毒

题目

P2444 [POI2000]病毒

做法

我们要找出无限安全字符串,则是这段字符串没有任意一点作为危险字符串的末点

我们对所有危险的字符串建AC自动机,然后跑一遍\(trie\)图,然后暴力判断是否有环,有环则说明存在无限安全字符串

My complete code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef int LL;
const LL maxn=40000;
LL tree[maxn][2],nod=1,flag[maxn],fail[maxn];
inline void Insert(char *s){
    LL Len(strlen(s+1)),now(0);
    for(LL i=1;i<=Len;++i){
        LL c=s[i]-'0';
        if(tree[now][c]==0)
            tree[now][c]=++nod;
        now=tree[now][c];
    }flag[now]=true;
}
char s[maxn];
inline void F_fail(){
    queue<LL>que;
    for(LL i=0;i<2;++i)
        if(tree[0][i])
            que.push(tree[0][i]);
    while(que.size()){
    	LL u=que.front(); que.pop();
    	flag[u]|=flag[fail[u]];
    	for(LL i=0;i<2;++i){
    		LL v(tree[u][i]);
    		if(v){
    			fail[v]=tree[fail[u]][i];
    			que.push(v);
            }else
                tree[u][i]=tree[fail[u]][i];
        }
    }
}
LL visit[maxn],forever[maxn];
void Dfs(LL u){
    if(flag[u]) return;
    if(visit[u]){
        printf("TAK");
        exit(0);
    }
    if(forever[u]) return;
    visit[u]=true,forever[u]=true;
    for(LL i=0;i<2;++i){
        LL v(tree[u][i]);
        if(v) Dfs(v);
    }
    visit[u]=false;
}
LL n;
int main(){
    scanf("%d",&n);
    for(LL i=1;i<=n;++i){
        scanf(" %s",s+1);
        Insert(s);
    }
    F_fail();
    Dfs(0);
    printf("NIE");
    return 0;
}
posted @ 2019-01-21 08:34  y2823774827y  阅读(163)  评论(0编辑  收藏  举报