BZOJ 2938: [Poi2000]病毒(AC自动机)

题意:

给你n个病毒代码,问你是否存在一个无限长的安全代码, TAK——假如存在这样的代码;NIE——如果不存在。

题解:

用病毒串建好AC自动机,然后在上面跑dfs判断是否有环即可。

不加vis标记也对,但是会TLE


AC代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 30050;
int nxt[MAXN][2],fail[MAXN],sta[MAXN],tot;
bool vis[MAXN],inque[MAXN],ok = false;
char s[MAXN];
inline void Insert(char *s){
    int root=0,len=strlen(s);
    for(int i=0;i<len;i++){
        if(!nxt[root][s[i]-'0']) nxt[root][s[i]-'0']=++tot;
        root=nxt[root][s[i]-'0'];
    }
    sta[root]=1;
}
inline void Build(){
    queue<int> que;
    for(int i=0;i<2;i++) if(nxt[0][i]) que.push(nxt[0][i]);
    while(!que.empty()){
        int u=que.front(); que.pop();
        for(int i=0;i<2;i++){
            if(nxt[u][i]){
                fail[nxt[u][i]] = nxt[fail[u]][i];
                sta[nxt[u][i]] |= sta[nxt[fail[u]][i]];
                que.push(nxt[u][i]);
            }else{
                nxt[u][i] = nxt[fail[u]][i];
            }
        }
    }
}
bool dfs(int u){
    inque[u]=true;
    for(int i=0;i<2;i++){
        if(inque[nxt[u][i]]) return true;
        if(vis[nxt[u][i]] || sta[nxt[u][i]]) continue;
        vis[nxt[u][i]]=true;
        if(dfs(nxt[u][i])) return true;
    }
    inque[u]=false;
    return false;
}
int main(){
    int n; scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%s",s),Insert(s);
    Build();
    if(dfs(0)) puts("TAK"); else puts("NIE");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值