首页 > 其他 > 详细

bzoj2938:[Poi2000]病毒

时间:2019-02-25 21:09:12      阅读:205      评论:0      收藏:0      [点我收藏+]

传送门

想到一个点上这个题目就没了:如果可以找到,那么必然是trie树上不经过病毒节点的一个环
接下来定义“病毒节点”:病毒节点就是病毒代码的最后一个字符,但是直接这样写会错,显然存在一个病毒代码是另一个病毒代码的子串的情况,那么一个病毒代码中就可能存在多个这样的病毒节点,怎么寻找呢?这就是一个多串匹配的问题了,AC自动机可以解决。
找环就用dfs就好了,记住一定要每个节点如果已经被尝试过就没有用了,再次尝试也找不到路径了,bzoj卡了不考虑这个的代码
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=3e4+10;queue<int>q;bool ed[maxn],vis[maxn],used[maxn];
int fail[maxn],n,rt=1,id=1,ch[maxn][2],ans;char s[maxn];
void insert(char *s,int d)
{
    int len=strlen(s+1);rt=1;
    for(rg int i=1;i<=len;i++)
    {
        int now=s[i]-'0';
        if(!ch[rt][now])ch[rt][now]=++id;
        rt=ch[rt][now];
    }
    ed[rt]=1;
}
void bfs()
{
    q.push(1);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(rg int i=0;i<2;i++)
        {
            if(!ch[x][i]){ch[x][i]=fail[x]?ch[fail[x]][i]:1;continue;}
            int j=fail[x],z=ch[x][i];q.push(z);
            while(j&&!ch[j][i])j=fail[j];
            if(j)fail[z]=ch[j][i];
            else fail[z]=1;
            ed[z]|=ed[fail[z]];
        }
    }
}
bool solve(int x)
{
    vis[x]=1;
    for(rg int i=0;i<2;i++)
    {
        if(vis[ch[x][i]])return 1;
        if(ed[ch[x][i]]||used[ch[x][i]])continue;
        used[ch[x][i]]=1;
        if(solve(ch[x][i]))return 1;
    }
    vis[x]=0;
    return 0;
}
int main()
{
    read(n);
    for(rg int i=1;i<=n;i++)scanf("%s",s+1),insert(s,i);
    bfs();if(solve(1))printf("TAK\n");else printf("NIE\n");
}

bzoj2938:[Poi2000]病毒

原文:https://www.cnblogs.com/lcxer/p/10433429.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!