P2444 [POI2000]病毒

题目描述

二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。

示例:

例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。

任务:

请写一个程序:

1.在文本文件WIR.IN中读入病毒代码;

2.判断是否存在一个无限长的安全代码;

3.将结果输出到文件WIR.OUT中。

输入输出格式

输入格式:

在文本文件WIR.IN的第一行包括一个整数n(n≤2000),表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。

输出格式:

在文本文件WIR.OUT的第一行输出一个单词:

TAK——假如存在这样的代码;

NIE——如果不存在。

输入输出样例

输入样例#1:

3
01
11
00000
输出样例#1:

NIE

这是一道非常有意思的AC自动机题目,首先我们可以根据读入的模式串把trie树给建好,然后把next数组搞出来,然后就GG了,这也没个文本串啊,这咋办啊?既然正着想不好办,我们可以考虑反过来想,如果有这样的一个字符串满足题目的要求不含有病毒代码,那么把这个字符串在trie树上跑回咋样呢?对啦,这个文本串一定不可以与任何一个模式串成功匹配,也就是说这个文本串会在trie树上跳来跳去,那么我们一定可以在trie树上找到一个环使得这个文本串会在这个环里来回跳。

看下面这个例子:

3

011

11

00000我们先把trie树建好,把next数组构造好,然后我们把文本串010101…跑一遍AC自动机,会发生什么呢?

不难看出,这个文本串会在上图中的0、1两个结点中来回跳,而且不能和任何一个模式串完全匹配。这样问题也就转化为了能否在trie树上利用next数组找到一个环使得这个环上不含有模式串的结束结点。看上去我们直接把所有模式串的结束结点打上标记然后直接dfs找环不就行了?貌似没有什么问题,但是这样做并不正确。

看下面的例子:

3

00

1

0100

我们继续把trie树和next数组给搞出来,然后进行dfs找环,但是这样会发生什么呢?我们会沿着上图中蓝色箭头所指的线路走,这样就会错误的判断为这个trie树上有环,但是显然这个树上是不存在环的,那么问题出在哪里呢?

对了,就是这个结点,根据next数组的含义,我们不难发现,只要这个结点的next链上含有模式串的结束结点,那么我们也应当把这个点打上模式串的结束标记,所以,我们还要把next链上存在模式串结束结点的点打上标记,这样就没有问题了。

 #include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#define maxn 60005
using namespace std; inline int read()
{
char c=getchar();
int res=,x=;
while(c<''||c>'')
{
if(c=='-')
x=-;
c=getchar();
}
while(c>=''&&c<='')
{
res=res*+(c-'');
c=getchar();
}
return res*x;
} int n,tot=,pd;
int tree[maxn][],nt[maxn],bo[maxn],dfn[maxn],vis[maxn];
char a[maxn];
queue<int>q; void trie(char *s)
{
int len=strlen(s),u=;
for(register int i=;i<len;i++)
{
int c=s[i]-'';
if(!tree[u][c])
{
tree[u][c]=++tot;
}
u=tree[u][c];
}
bo[u]=;
} void bfs()
{
for(register int i=;i<;i++)
{
tree[][i]=;
}
nt[]=;q.push();
while(q.size())
{
int u=q.front();q.pop();
for(register int i=;i<;i++)
{
if(!tree[u][i])
tree[u][i]=tree[nt[u]][i];
else
{
int v=tree[u][i];
q.push(v);
nt[v]=tree[nt[u]][i];
}
}
}
} void dfs(int x)
{
if(pd) return;
for(int i=;i<=;i++)
{
if(!vis[tree[x][i]]&&!bo[tree[x][i]])
{
vis[tree[x][i]]=;
dfs(tree[x][i]);
vis[tree[x][i]]=;
}
else if(!bo[tree[x][i]]&&vis[tree[x][i]])
{
pd=;
return;
}
}
} int main()
{
n=read();
for(register int i=;i<=n;i++)
{
scanf("%s",a);
trie(a);
}
bfs();
vis[]=;
for(int i=;i<=tot;i++)
{
int k=i,m=;
while(k>)
{
if(bo[k])
m=k;
k=nt[k];
}
k=i;
if(m==) continue;
while(k>)
{
if(k==m) break;
bo[k]=;
k=nt[k];
}
}
dfs();
if(pd)
{
printf("TAK\n");
}
else
{
puts("NIE");
}
return ;
}

P2444 [POI2000]病毒的更多相关文章

  1. 洛谷 P2444 [POI2000]病毒 解题报告

    P2444 [POI2000]病毒 题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已 ...

  2. P2444 [POI2000]病毒 AC自动机

    P2444 [POI2000]病毒 #include <bits/stdc++.h> using namespace std; ; struct Aho_Corasock_Automato ...

  3. [洛谷P2444] [POI2000]病毒

    洛谷题目链接:[POI2000]病毒 题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会 ...

  4. 洛谷P2444 [POI2000]病毒(AC自动机,DFS求环)

    洛谷题目传送门 AC自动机入门--yyb巨佬的博客 AC自动机入手经典好题(虽然年代久远) 有了fail指针,trie树就不是原来的树型结构了,我们可以把它叫做trie图,由父节点向子节点连的边和fa ...

  5. 【洛谷】P2444 [POI2000]病毒——AC自动机

    题目链接 题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段, ...

  6. 2021.11.10 [POI2000]病毒(AC自动机)

    2021.11.10 [POI2000]病毒(AC自动机) https://www.luogu.com.cn/problem/P2444 题意: 二进制病毒审查委员会最近发现了如下的规律:某些确定的二 ...

  7. BZOJ 2938: [Poi2000]病毒 [AC自动机 拓扑排序]

    2938: [Poi2000]病毒 题意:判断是否存在无限长的不含模式串的字符串.只有01. 建出套路DP的转移图,判断有环就行了 练习一下拓扑排序 #include <iostream> ...

  8. BZOJ_2938_[Poi2000]病毒_AC自动机

    BZOJ_2938_[Poi2000]病毒_AC自动机 Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们 ...

  9. BZOJ 2938: [Poi2000]病毒

    2938: [Poi2000]病毒 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 360[Submit][Status][Di ...

随机推荐

  1. Go语言中的Package问题

    问题一.Go使用Package组织源码的好处是什么? 1.任何源码属于一个包 2.用包组织便于代码的易读和复用 问题二.Go语言中Package的种类 Go语言中存在两种包.一种是可执行程序的包.一种 ...

  2. VUE项目中使用mint-ui框架总结

    针对PC端,element-ui可谓是首选了,UI体验效果很好. element-ui 框架官网:http://element.eleme.io/#/zh-CN/component/installat ...

  3. js的一些点

    1 闭包 闭包就是说,能够读取其他函数内部变量的函数. 其实这句话我不是很明白,因为我觉得闭包的作用是: 延迟函数执行 模拟私有变量 根据第二点的描述,应该是阻止其他东西访问自身私有成员,到了这怎么变 ...

  4. 【js】前端 js/jquery 常用代码和实践

    1.获取某天后几天的日期 //d为传入的日期 days为d后面的几天function getAfterDate(d,days){ var dd = new Date(d); dd.setDate(dd ...

  5. 数据库MySQL——安装

    MySQL 安装 Mysql安装: 1.通过二进制的方式安装 二进制安装方式中,包括rpm版本以及glibc版本. rpm版本就是在特定linux版本下编译的,如果你的linux版本匹配,就可以安装; ...

  6. MySQL表与表之间的关系

    表与表之间的关系 表1 foreign key 表2 则表1的多条记录对应表2的一条记录,即多对一 利用foreign key的原理我们可以制作两张表的多对多,一对一关系 多对多: 表1的多条记录可以 ...

  7. 一文入门HTML5

    1.HTML5 上节回顾:一文读懂ES6(附PY3对比) | 一文入门NodeJS 演示demo:https://github.com/lotapp/BaseCode/tree/master/java ...

  8. 使用django执行数据更新命令时报错:django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependency users.00 01_initial on database 'default'.

    如果在重新封装更新用户表之前,已经更新了数据表,在数据库中已经有了django相关的依赖表,就会报错: django.db.migrations.exceptions.InconsistentMigr ...

  9. django 1.开发接口环境搭建

    首先需要的环境: pycharm Python 3.6.0 django 2.1.3        安装命令: pip3 install django   查看版本号和安装的路径: pip show ...

  10. SpringBoot文件上传(MVC情况和webFlux情况)

    MVC情况 引入依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...