【洛谷】P2444 [POI2000]病毒——AC自动机
题目描述
二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码。如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的。现在委员会已经找出了所有的病毒代码段,试问,是否存在一个无限长的安全的二进制代码。
示例:
例如如果{011, 11, 00000}为病毒代码段,那么一个可能的无限长安全代码就是010101…。如果{01, 11, 000000}为病毒代码段,那么就不存在一个无限长的安全代码。
任务:
请写一个程序:
1.在文本文件WIR.IN中读入病毒代码;
2.判断是否存在一个无限长的安全代码;
3.将结果输出到文件WIR.OUT中。
输入格式
在文本文件WIR.IN的第一行包括一个整数n(n\le 2000)(n≤2000),表示病毒代码段的数目。以下的n行每一行都包括一个非空的01字符串——就是一个病毒代码段。所有病毒代码段的总长度不超过30000。
输出格式
在文本文件WIR.OUT的第一行输出一个单词:
TAK——假如存在这样的代码;
NIE——如果不存在。
输入输出样例
输入
3
01
11
00000
输出
NIE
分析
想办法让那串无限长的字符串不断的在树上失配,然后不断的走fail指针最后进入一个循环即可
即在树上dfs,保证不经过任何字符串尾节点使得找到一个树上环
AC code
#include <bits/stdc++.h>
using namespace std;
/*
* AC 自动机:多个模式串去匹配一个串,求有多少个模式串与主串有匹配内容
*
* 使用操作:
* 1、把每一个模式串插入到树中 insert
* 2、build
* 3、使用 query 询问有多少个模式串匹配
*/
const int CHAR_NUM = 2;//仅小写
const int MAXN = 2100;//模式串个数
const int MAXM = 30100;//模式串最长长度
const int NUM = MAXN * MAXM;//空间=个数*长度,稳
struct Trie {
int c[NUM][CHAR_NUM], val[NUM], fail[NUM], cnt;
void insert(char *s) {
int len = strlen(s);
int now = 0;
for (int i = 0; i < len; i++) {
// int v = s[i] - 'a';
int v = s[i] - '0';
if (!c[now][v])c[now][v] = ++cnt;
now = c[now][v];
}
val[now]++;
}
void build() {
queue<int> q;
for (int i = 0; i < CHAR_NUM; i++)if (c[0][i])fail[c[0][i]] = 0, q.push(c[0][i]);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = 0; i < CHAR_NUM; i++)
if (c[u][i])fail[c[u][i]] = c[fail[u]][i], q.push(c[u][i]);
else c[u][i] = c[fail[u]][i];
}
}
int query(char *s) {
int len = strlen(s);
int now = 0, ans = 0;
for (int i = 0; i < len; i++) {
// now = c[now][s[i] - 'a'];
now = c[now][s[i] - '0'];
for (int t = now; t && ~val[t]; t = fail[t])ans += val[t], val[t] = -1;
}
return ans;
}
} AC;
char s[30100];
bool vis[NUM];
bool dfs(int cur) {
for (int i = 0; i < CHAR_NUM; ++i) {
int x = AC.c[cur][i];
if (!AC.val[x]) {
bool flag = false;
int t = x;
while (t) {
if (AC.val[t]) {
flag = true;
break;
}
t = AC.fail[t];
}
if (flag)
continue;
if (vis[x])
return true;
vis[x] = true;
if (dfs(x)) {
return true;
}
vis[x] = false;
}
}
return false;
}
void solve() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> s;
AC.insert(s);
}
AC.build();
vis[0] = true;
bool flag = dfs(0);
if (flag) {
cout << "TAK" << endl;
} else {
cout << "NIE" << endl;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
#ifdef ACM_LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
long long test_index_for_debug = 1;
char acm_local_for_debug;
while (cin >> acm_local_for_debug) {
cin.putback(acm_local_for_debug);
if (test_index_for_debug > 20) {
throw runtime_error("Check the stdin!!!");
}
auto start_clock_for_debug = clock();
solve();
auto end_clock_for_debug = clock();
cout << "Test " << test_index_for_debug << " successful" << endl;
cerr << "Test " << test_index_for_debug++ << " Run Time: "
<< double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
cout << "--------------------------------------------------" << endl;
}
#else
solve();
#endif
return 0;
}
【洛谷】P2444 [POI2000]病毒——AC自动机的更多相关文章
- 洛谷 P2444 [POI2000]病毒 解题报告
P2444 [POI2000]病毒 题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已 ...
- P2444 [POI2000]病毒 AC自动机
P2444 [POI2000]病毒 #include <bits/stdc++.h> using namespace std; ; struct Aho_Corasock_Automato ...
- 洛谷P2444 [POI2000]病毒(AC自动机,DFS求环)
洛谷题目传送门 AC自动机入门--yyb巨佬的博客 AC自动机入手经典好题(虽然年代久远) 有了fail指针,trie树就不是原来的树型结构了,我们可以把它叫做trie图,由父节点向子节点连的边和fa ...
- [洛谷P2444] [POI2000]病毒
洛谷题目链接:[POI2000]病毒 题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会 ...
- [POI2000]病毒 --- AC自动机
[POI2000]病毒 题目描述: 二进制病毒审查委员会最近发现了如下的规律: 某些确定的二进制串是病毒的代码. 如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的. 现在委员会已经找 ...
- 【BZOJ2938】[Poi2000]病毒 AC自动机+DFS
[BZOJ2938][Poi2000]病毒 Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码 ...
- 洛谷-P5357-【模板】AC自动机(二次加强版)
题目传送门 -------------------------------------- 过年在家无聊补一下这周做的几道AC自动机的模板题 sol:AC自动机,还是要解决跳fail边产生的重复访问,但 ...
- BZOJ 2938: [Poi2000]病毒 [AC自动机 拓扑排序]
2938: [Poi2000]病毒 题意:判断是否存在无限长的不含模式串的字符串.只有01. 建出套路DP的转移图,判断有环就行了 练习一下拓扑排序 #include <iostream> ...
- BZOJ2938[Poi2000]病毒——AC自动机
题目描述 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出了所有的病毒代码段,试问,是否 ...
随机推荐
- array, matrix, list and dataframe
总结一下"入门3R"(Reading, 'Riting, 'Rrithmetic)中的读和写,不同的数据结构下的读写还是有点区别的. vector 命名 12 month.days ...
- PHPExcel之蛋疼
限制了内存,处理个80+K的表就会GG,所以还要尽量删空行,选中某一行如A3,ctrl+shift+↓然后ctrl+小键盘的减号最后需要ctrl+s
- 游LeetCode一月之闲谈
今年的2月比往常更长,不是因为比往年多了一天,而是被病毒隔离在家的日子显得十分漫长.如果再不给自己找点事情做的话,且不论身体方面的健康状况,精神方面可能也会有些隐忧.做为一名工程师,适时地读上几本平日 ...
- C++走向远洋——62(项目二1、类模板)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- 如何在自己的CSDN博客中增添【高大上】的博客栏目?
前几天看到过一位博主的博客界面,向下看 ☟ (博主对不起啊!把你的公众号给抹了~~~),感觉做这个东西挺好玩的,而且我竟然找不到在哪个地方可以设置!在百度上也没有搜到教程,最后问了一下贺老师知道了入口 ...
- 下一代网际协议IPv6
下一代网际协议IPv6 一.解决 IP 地址耗尽的措施 从计算机本身发展以及从因特网规模和网络传输速率来看,现在 IPv4 已很不适用. 最主要的问题就是 32 位的 IP 地址不够用. 在 2019 ...
- CountDownLatch源码探究 (JDK 1.8)
CountDownLatch能够实现让线程等待某个计数器倒数到零的功能,之前对它的了解也仅仅是简单的使用,对于其内部如何实现线程等待却不是很了解,最好的办法就是通过看源码来了解底层的实现细节.Coun ...
- plsql-工具安装部署及使用配置
参考文档链接:https://blog.csdn.net/li66934791/article/details/83856225 简介: PL/SQL Developer是一个集成开发环境,专门开发面 ...
- Redis简单的数据操作(增删改查)
#Redis简单的数据操作(增删改查): 字符串类型 string 1. 存储: set key value 127.0.0.1:6379> set username zhangsan OK 2 ...
- MySQL之单表多表查询
#1.单表查询 #单表查询语法 select <字段1,字段2....> from <表名> where <表达式> group by field 分组 havin ...