https://www.lydsy.com/JudgeOnline/problem.php?id=2938

题意:给出N个01病毒序列,询问是否存在一个无限长的串不存在病毒序列

正常来说,想要寻找一个串是否出现这些01序列可以直接跑AC自动机,这题反向问有没有无限长的不出现,说明在AC自动机上询问的时候,要避免经过所有病毒串标记的end结点以及需要寻找一个可以无限跑的环。

所以我们将字典树的边和失配指针的边都看作是一条有向边,如果存在一个环上没有病毒结尾的标记,那么他就是合法的。

值得一提的是,fail指针的意义是指向最长公共前后缀的下一个结点,因此如果一个节点的fail指针指向了一个危险结点,则这个结点也是危险的,因为他指向的点一定是他的后缀。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 5e4 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
vector<int>Q[maxn];
int a[maxn];
struct AC{
int next[][],fail[];
int end[],ind[];;
int root,tot;
int newnode(){
next[tot][] = next[tot][] = -;
end[tot] = ; ind[tot] = ;
return tot++;
}
void init(){
tot = ;
root = newnode();
}
void insert(char *str){
int p = root;
for(int i = ;str[i]; i ++){
int id = str[i] - '';
if(next[p][id] == -) next[p][id] = newnode();
p = next[p][id];
}
end[p] = ;
}
void Build(){
queue<int>Q;
for(int i = ; i < ; i ++){
if(next[root][i] != -){
fail[next[root][i]] = root;
Q.push(next[root][i]);
}else{
next[root][i] = root;
}
}
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(int i = ; i < ; i ++){
if(next[u][i] == -){
next[u][i] = next[fail[u]][i];
}else{
fail[next[u][i]] = next[fail[u]][i];
if(end[fail[next[u][i]]]){
end[next[u][i]] = ;
}
Q.push(next[u][i]);
}
}
}
}
bool solve(){
for(int i = ; i < tot; i ++){
if(end[i]) continue;
ind[next[i][]]++;
ind[next[i][]]++;
}
queue<int>Q;
for(int i = ; i < tot; i ++){
if(!end[i] && !ind[i]) Q.push(i);
}
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(int i = ; i < ; i ++){
ind[next[u][i]]--;
if(!end[next[u][i]] && !ind[next[u][i]])
Q.push(next[u][i]);
}
}
for(int i = ; i < tot; i ++){
if(!end[i] && ind[i]) return true;
}
return false;
}
}ac;
char str[maxn];
int main(){
Sca(N);
ac.init();
For(i,,N){
scanf("%s",str);
ac.insert(str);
}
ac.Build();
if(ac.solve()) puts("TAK");
else puts("NIE");
return ;
}

bzoj2938 AC自动机 + 拓扑排序找环的更多相关文章

  1. 【CodeForces】915 D. Almost Acyclic Graph 拓扑排序找环

    [题目]D. Almost Acyclic Graph [题意]给定n个点的有向图(无重边),问能否删除一条边使得全图无环.n<=500,m<=10^5. [算法]拓扑排序 [题解]找到一 ...

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

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

  3. Legal or Not(拓扑排序判环)

    http://acm.hdu.edu.cn/showproblem.php?pid=3342 Legal or Not Time Limit: 2000/1000 MS (Java/Others)   ...

  4. POJ 1094 Sorting It All Out(拓扑排序+判环+拓扑路径唯一性确定)

    Sorting It All Out Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 39602   Accepted: 13 ...

  5. LightOJ1003---Drunk(拓扑排序判环)

    One of my friends is always drunk. So, sometimes I get a bit confused whether he is drunk or not. So ...

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

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

  7. bzoj2938(ac自动机)

    刚学了ac自动机,去hzwer上找了道练习题: 串是安全的就说明ac自动机不会找到匹配,考虑ac自动机的匹配过程: 我们把val等于1的点删掉和fail指针指向被删掉的点删掉: 如果剩下的图有环,就有 ...

  8. 传递 hdu 5961 拓扑排序有无环~

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5961 题目为中文,这里就不描述题意了. 思路: 从题目陈述来看,他将一个有向图用一个邻接矩阵来表示,并且分 ...

  9. HDU1811 拓扑排序判环+并查集

    HDU Rank of Tetris 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1811 题意:中文问题就不解释题意了. 这道题其实就是一个拓扑排序判圈 ...

随机推荐

  1. JarvisOJ Basic 爱吃培根的出题人

    听说你也喜欢吃培根?那我们一起来欣赏一段培根的介绍吧: bacoN is one of aMerICa'S sWEethEartS. it's A dARlinG, SuCCulEnt fOoD tH ...

  2. Let's Encrypt免费泛域名证书申请

    一. 下载acme.sh,以下四条命令任选一条即可 curl https://get.acme.sh | shwget -O - https://get.acme.sh | sh curl https ...

  3. 洛谷P1550打井

    打井 题目 该题是一个最小生成树的好题,但是比起一般的最小生成树来说他不仅仅有各个井相连,而且还要和地下水相连,所以地下水我们也可以看成一口井. 代码 #include <bits/stdc++ ...

  4. ☆ [HDU4825] Xor Sum「最大异或和(Trie树)」

    传送门:>Here< 题意:给出一个集合,包含N个数,每次询问给出一个数x,问x与集合中的一个数y异或得到最大值时,y是多少? 解题思路 由于N,M非常大,暴力显然不行.抓住重点是异或,所 ...

  5. 记一次Java调优案例分析

    上周,一同学给我发来,他们那里的案例 一看就是新生代产生过多对象,肯定是批量或者循环操作导致的,导致新生代一直在进行回收导致. 如果是老生代出现这样的问题,大部分情况下是列表或者集合导致的. 因此我们 ...

  6. Java实现一个双向链表的倒置功能

    题目要求:Java实现一个双向链表的倒置功能(1->2->3 变成 3->2->1) 提交:代码.测试用例,希望可以写成一个Java小项目,可以看到单元测试部分 该题目的代码, ...

  7. 七牛云 qshell 使用

    七牛云 qshell 控制台工具上传 命令:qshell fput another1 demo.txt /users/tianyang/demo.txt ======================= ...

  8. 爬虫_豆瓣电影top250 (正则表达式)

    一样的套路,就是多线程还没弄 import requests import re import json headers = 'Mozilla/5.0 (Windows NT 10.0; WOW64) ...

  9. Leetcode 215. 数组中的第K个最大元素 By Python

    在未排序的数组中找到第 k 个最大的元素.请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素. 示例 1: 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 ...

  10. expect交互式安装软件

    公司一些宿主机需要安装软件,吴老师要求写一个安装脚本: 脚本思路:首先要把安装的包拷贝到每台机器上,然后要让每台机器都运行一次安装命令:就想到了应用scp.ssh命令,但这两个命令需要输入对端密码,需 ...