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. Newton方法

    Newton方法主要解决无等式约束和等式约束的最优化方法. 1.函数进行二阶泰勒展开近似 Taylor近似函数求导等于0进而得到Newton步径.(搜索方向) 2.Newton减量(停止条件) 当1/ ...

  2. Nintex Forms Drop-Down "z-index"

    Now we’ve got the issue, that if we are working with a “Person-Column”, the drop-down where you can ...

  3. JAVA web 使用有盟推送总结

    仔细阅读文档,下边的都是废话. 为了省事,iOS和Android 提供了所有了参数,需要那个了修改传参. //ios actionURL为自定义参数 $.ajax({ type : "POS ...

  4. Java常用调试技巧(转)

    调试不仅可以查找到应用程序缺陷所在,还可以解决缺陷.对于Java程序员来说,他们不仅要学会如何在Eclipse里面开发像样的程序,更需要学会如何调试程序.本文介绍了Java程序员必知的10个调试技巧, ...

  5. IntelliJ IDEA Tomcat启动VM Options配置

    -server -XX:PermSize=512M -XX:MaxPermSize=1024m -Dfile.encoding=UTF-8 JDK8中用metaspace代替permsize,因此在许 ...

  6. HTML知识点总结[部分]

    Web服务的本质(socket实例) import socket def handle_request(client): buf = client.recv(1024) client.send(byt ...

  7. P1427 小鱼念数字

    P1427 题目描述 小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字(长度不一定,以0结束,最多不超过100个,数字不超过2^32-1),记住了然后反着念出来(表示结束的数字0就不要念出来了) ...

  8. 洛谷P3258 松鼠的新家

    树上差分 这应该是一道很简单的树上差分了..就是问每个点被覆盖了多少次. 要注意我们最后dfs后,要把除第一个节点以外的所有点的-1,因为有些点作为起点和终点覆盖了两次,按照题目意思是不用覆盖两次的. ...

  9. Appium环境的安装以及一路上的坑

    Appium环境的安装以及一路上的坑 第一步环境的安装 l  javaJDK的安装以及环境变量的配置这个我就不说了网上的教程全都是,搜一个安装一下吧 l  AndroidSDK的安装也是如此我是直接安 ...

  10. MySQL 报错 1055

    具体报错 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'exer.student.sid' w ...