bzoj2938 AC自动机 + 拓扑排序找环
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自动机 + 拓扑排序找环的更多相关文章
- 【CodeForces】915 D. Almost Acyclic Graph 拓扑排序找环
[题目]D. Almost Acyclic Graph [题意]给定n个点的有向图(无重边),问能否删除一条边使得全图无环.n<=500,m<=10^5. [算法]拓扑排序 [题解]找到一 ...
- BZOJ 2938: [Poi2000]病毒 [AC自动机 拓扑排序]
2938: [Poi2000]病毒 题意:判断是否存在无限长的不含模式串的字符串.只有01. 建出套路DP的转移图,判断有环就行了 练习一下拓扑排序 #include <iostream> ...
- Legal or Not(拓扑排序判环)
http://acm.hdu.edu.cn/showproblem.php?pid=3342 Legal or Not Time Limit: 2000/1000 MS (Java/Others) ...
- POJ 1094 Sorting It All Out(拓扑排序+判环+拓扑路径唯一性确定)
Sorting It All Out Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 39602 Accepted: 13 ...
- LightOJ1003---Drunk(拓扑排序判环)
One of my friends is always drunk. So, sometimes I get a bit confused whether he is drunk or not. So ...
- 洛谷P2444 [POI2000]病毒(AC自动机,DFS求环)
洛谷题目传送门 AC自动机入门--yyb巨佬的博客 AC自动机入手经典好题(虽然年代久远) 有了fail指针,trie树就不是原来的树型结构了,我们可以把它叫做trie图,由父节点向子节点连的边和fa ...
- bzoj2938(ac自动机)
刚学了ac自动机,去hzwer上找了道练习题: 串是安全的就说明ac自动机不会找到匹配,考虑ac自动机的匹配过程: 我们把val等于1的点删掉和fail指针指向被删掉的点删掉: 如果剩下的图有环,就有 ...
- 传递 hdu 5961 拓扑排序有无环~
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5961 题目为中文,这里就不描述题意了. 思路: 从题目陈述来看,他将一个有向图用一个邻接矩阵来表示,并且分 ...
- HDU1811 拓扑排序判环+并查集
HDU Rank of Tetris 题目:http://acm.hdu.edu.cn/showproblem.php?pid=1811 题意:中文问题就不解释题意了. 这道题其实就是一个拓扑排序判圈 ...
随机推荐
- 【题解】Hanoi
题目描述 有三根柱A,B,C.在柱A上有N块盘片,所有盘片都是大的在下面,小片能放在大片上面.并依次编好序号,现要将A上的N块片移到C柱上,每次只能移动一片,而且在同一根柱子上必须保持上面的盘片比下面 ...
- github-share报错无法读取远程仓库
报错:github Could not read from remote repository 1.github创建仓库成功,而push报告此错误 2.考虑远程仓库名与本地项目名/文件夹名不匹配 3. ...
- 微信小程序——安装开发工具和环境【二】
准备 开发工具下载 获取APPID 安装工具 安装 接受协议 选择安装位置 等待安装完成 安装完成 选择项目 选择小程序 填写信息 确定 无误后,点击确定进入开发页面 建立普通快速启动模板界面
- HDU 1021 斐波那契
参考自:https://www.cnblogs.com/ECJTUACM-873284962/p/6404504.html Fibonacci Again Time Limit: 2000/1000 ...
- GGS-DDU HDU - 4966
GGS-DDU Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total S ...
- Golden Eggs HDU - 3820(最小割)
Golden Eggs Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 【XSY2715】回文串 树链剖分 回文自动机
题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(tra ...
- 【BZOJ3236】【AHOI2013】作业 线段树 分治 树状数组
题目描述 给你一个长度为\(n\)的数列,还有\(m\)个询问,对于每个询问\((l,r,a,b)\),输出1.区间\([l,r]\)有多少范围在\([a,b]\)的数:2.区间\([l,r]\)有多 ...
- sshfs && tailon
sshfs 安装yum install glib2-devel fuse-sshfs官方版本地址https://github.com/libfuse/sshfs/releases目前最新版本:wget ...
- [NOIp2008] 双栈排序 (二分图染色 + 贪心)
题意 给你一个长为 \(n\) 的序列 \(p\) ,问是否能够通过对于两个栈进行 push, pop(print) 操作使得最后输出序列单调递增(即为 \(1 \cdots n\) ),如果无解输出 ...