题目描述

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

示例:

例如如果{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——如果不存在。

输入输出样例

输入样例#1: 复制

3
01
11
00000
输出样例#1: 复制

NIE

题意:

给n个模式串,问能不能找到一个无限长的文本串,使得模式串没有出现在文本串里。

思路:

看到题目没想法......看了题解

我们会发现正常的AC自动机都是在文本串中去匹配模式串,现在不要模式串出现,那么也就是说希望Trie中被标记为模式串结尾的节点不要出现。我们将这个称为危险标记。而想要无限长的文本串,其实也就是在匹配过程中能否找到这样一个环,使得环上的节点都是安全的。

首先我们还是先建立fail数组,需要注意的是,如果一个节点的fail指针指向的节点是危险的,那么他本身也是危险的。

因为一个节点x的fail指针指向的节点y表示的是以y作为结尾的前缀与以x为结尾的前缀的后缀匹配的最长部分,也就是说根节点到y一定是在根节点到x中出现过的。

然后dfs,用一个数组vis标记路径,一个数组f标记是否访问过。vis在dfs结束后要恢复,是用来判断当前路径是否形成环的。

 #include <iostream>
#include <set>
#include <cmath>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
#define inf 0x7f7f7f7f int n;
const int maxn = ; struct Tree{
int fail;//失配指针
int vis[];//子节点位置
int ed;//标记有几个单词以这个节点结尾
}AC[maxn];
string s;
int tot = ; void build(string s)
{
int len = s.length();
int now = ;//字典树当前指针
for(int i = ; i < len; i++){
if(AC[now].vis[s[i] - ''] == ){
AC[now].vis[s[i] - ''] = ++tot;
}
now = AC[now].vis[s[i] - ''];
}
AC[now].ed = ;
} void get_fail()
{
queue<int> que;
for(int i = ; i < ; i++){
if(AC[].vis[i] != ){
AC[AC[].vis[i]].fail = ;
que.push(AC[].vis[i]);
}
}
while(!que.empty()){
int u = que.front();
que.pop();
for(int i = ; i < ; i++){
if(AC[u].vis[i] != ){
AC[AC[u].vis[i]].fail = AC[AC[u].fail].vis[i];
if(AC[AC[u].fail].ed){
AC[u].ed = ;
}
que.push(AC[u].vis[i]);
}
else{
AC[u].vis[i] = AC[AC[u].fail].vis[i];
}
}
}
} bool vis[maxn], f[maxn];
void dfs(int rt)
{
vis[rt] = true;
for(int i = ; i < ; i++){
if(vis[AC[rt].vis[i]]){
printf("TAK\n");
exit();
}
else if(!AC[AC[rt].vis[i]].ed && !f[AC[rt].vis[i]]){
f[AC[rt].vis[i]] = true;
dfs(AC[rt].vis[i]);
}
}
vis[rt] = false;
} int main()
{
scanf("%d", &n);
for(int i = ; i < n; i++){
cin>>s;
build(s);
}
AC[].fail = ;
get_fail();
dfs();
printf("NIE\n");
//cout<<s[maxid]<<endl;
//cout<<AC_query(s)<<endl;
return ;
}

洛谷P2444 病毒【AC自动机】的更多相关文章

  1. 洛谷 - P2444 - 病毒 - AC自动机

    https://www.luogu.org/problemnew/show/P2444 有点恶心,不太明白fail的意义. #include<bits/stdc++.h> using na ...

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

    正解:AC自动机 解题报告: 传送门! 首先看到这种题目二话不说先把trie树和fail指针建立起来 然后就想鸭,如果我们想让模式串和文本串尽量不能匹配,就要想办法让它跳fail指针,而不是继续往下走 ...

  3. 洛谷 - P3966 - 单词 - AC自动机

    https://www.luogu.org/problemnew/show/P3966 因为文本串就是字典本身,所以这个和平时的AC自动机不太一样.平时的query要沿着fail树把子树的出现次数依次 ...

  4. 洛谷P3808 & P3796 AC自动机模板

    题目:P3808:https://www.luogu.org/problemnew/show/P3808 P3796:https://www.luogu.org/problemnew/show/P37 ...

  5. 洛谷.3121.审查(AC自动机 链表)

    题目链接 //删掉一个单词需要前移一段位置,用链表维护就好了 复杂度O(sum(len)) #include <cstdio> #include <cstring> #defi ...

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

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

  7. 【洛谷 P2444】 [POI2000]病毒(AC自动机)

    题目链接 这么多字符串,肯定是自动机啦. 先建出AC自动机,然后怎么表示一个安全代码没有病毒代码呢? 就是存在一条路径不经过有病毒代码段结尾的节点呗. 所以呢?有环啊!dfs一下救星了. #inclu ...

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

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

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

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

随机推荐

  1. e641. 使一个组件成为拖放目标

    public class DropTargetComponent extends JComponent implements DropTargetListener { public DropTarge ...

  2. Linux基础知识之man手册的使用

    在Linux中man的使用频率应该是很高的,灵活运用它可以让自己快速的掌握一个不熟悉命令的使用方法.下面来介绍下man 环境CentOS6.8 man - format and display the ...

  3. js中以键值对的形式当枚举

    js中以键值对的形式当枚举var Penum= { B: "姓名", C: "所属居委", D: "证件号", E: "性别&qu ...

  4. 安装 oracle [转]

    先下载3个东西:链接忘记了,大家自己找一下 1  ORA+11+G+R2+server+64bit+for+windows.iso  (Oracle 安装文件) 2  PLSql 3  oracle6 ...

  5. Project Navigator Help: Creating a Workspace in Xcode

    Creating a Workspace Start a multiproduct development endeavor by creating a workspace. 1.Choose Fil ...

  6. arugsJS 入门

    一款优秀的前端框架——AngularJS     前  言 AngularJS是一款为了克服HTML在构建应用上的不足而设计的优秀的前端JS框架.AngularJS有着诸多特性,最为核心的是:MVC. ...

  7. RGB 颜色对照表

    R G B 值   R G B 值   R G B 值 黑色 0 0 0 #000000 黄色 255 255 0 #FFFF00 浅灰蓝色 176 224 230 #B0E0E6 象牙黑 41 36 ...

  8. 立即调用的函数表达式---IIFE

    有些人则称为“自执行的匿名函数” 在闭包中,我们经常需要使用到匿名函数,我感觉闭包就是一种匿名函数,子集. 但是直接在匿名函数后面调用函数是会出错的.比如: function () { alert(& ...

  9. Ubuntu16.04下Mongodb(离线安装方式|非apt-get)安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 说在前面的话  首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu LTS \n \l r ...

  10. C51中遇到一个有关data与xdata的问题,已解决

    环境: 我在某个C文件定义了一个结构体变量,然后该变量仅仅是在本文件内被一个函数使用,然后又在中断中调用了该函数,目的是改变一个IO口的输出状态,结果运行时怎么也达不到要的效果. struct BE ...