bzoj 2938

收获:

  1、AC自动机可以在建立fail时将一些不存在的儿子指针指向对应的位置。

  2、判断环时不要想当然地写个这样的版本:

bool dfs( int u ) {
    if( vis[u] ) return true;
    vis[u] = true;
    for( int t=0; t<g[u].size(); t++ ) {
        int v=g[u][t];
        if( dfs(v) ) return true;
    }
    vis[u] = false;
    return false;
}

它是O(n^2)的,然后我就不知到为什么T了,搞了好久才弄好。

  3、存在一个无限长的不与给定pattern匹配的text,那么在该text上跑ac自动机会无限循环,反之一定会在有限的时间内结束。

 1 /**************************************************************
 2     Problem: 2938
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:40 ms
 7     Memory:2316 kb
 8 ****************************************************************/
 9
10 #include <cstdio>
11 #include <cstring>
12 #include <cstdlib>
13 #include <queue>
14 #define maxn 60010
15 using namespace std;
16
17 int son[maxn][2], fail[maxn], ikey[maxn], ntot;
18 int vis[maxn], cir[maxn];
19 char str[maxn];
20
21 void insert( const char *P ) {
22     int n=strlen(P);
23     int u=0;
24     for( int i=0; i<n; i++ ) {
25         int c=P[i]-‘0‘;
26         if( !son[u][c] ) son[u][c] = ++ntot;
27         u=son[u][c];
28     }
29     ikey[u] = true;
30 }
31 void build_fail() {
32     queue<int> qu;
33     for( int c=0; c<2; c++ ) {
34         int v=son[0][c];
35         if( !v ) continue;
36         qu.push( v );
37         fail[v] = 0;
38     }
39     while( !qu.empty() ) {
40         int u=qu.front();
41         qu.pop();
42         for( int c=0; c<2; c++ ) {
43             int v=son[u][c];
44             int w=fail[u];
45             if( !v ) {
46                 son[u][c] = son[fail[u]][c];
47                 continue;
48             }
49             while( w && !son[w][c] ) w=fail[w];
50             fail[v] = son[w][c];
51             ikey[v] |= ikey[fail[v]];
52             qu.push( v );
53         }
54     }
55 }
56 void dfs( int u ) {
57     vis[u] = true;
58     for( int c=0; c<2; c++ ) {
59         int v=son[u][c];
60         if( cir[v] || ikey[v] ) continue;
61         if( !vis[v] )
62             dfs(v);
63         else {
64             printf( "TAK\n" );
65             exit(0);
66         }
67     }
68     cir[u] = true;
69 }
70 int main() {
71     int n;
72     scanf( "%d", &n );
73     for( int i=0; i<n; i++ ) {
74         scanf( "%s", str );
75         insert( str );
76     }
77     build_fail();
78     dfs( 0 );
79     printf( "NIE\n" );
80 }

时间: 2024-10-09 18:18:35

bzoj 2938的相关文章

[bzoj 2938] [Poi2000]病毒]

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2938 [Poi2000]病毒 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 870  Solved: 447[Submit][Status][Discuss] Description 二进制病毒审查委员会最近发现了如下的规律:某些确定的二进制串是病毒的代码.如果某段代码中不存在任何一段病毒代码,那么我们就称这段代码是安全的.现在委员会已经找出

bzoj 2938 AC自动机

根据题意建出trie图,代表单词的点不能走,直接或间接指向它的点也不能走.这样的话如果能在图中找到一个环的话就是TAK,否则是NIE. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #define N 30005 7 using namespace std; 8 int n;bool fla

BZOJ 2938 Poi2000 病毒 AC自动机+拓扑排序

题目大意:给定n个01串,问是否存在一个无限长的01串,不包含这n个01串中的任何一个 建出Trie图之后判环即可 我这傻逼一开始居然跑了一个DFS去判环23333 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 30300 using namespace std; int n; char s[M]; namespace Aho_C

【BZOJ】【2938】【POI2000】病毒

AC自动机 好题>_<(其实是一次AC有些感动) 嗯要找到无限长的一个字符串不包含任何一个模板串,就意味着在AC自动机(Trie图)上找到一个不经过任何一个危险结点的环,深搜一下就好了……记得离开某个结点的时候要清除标记!有点像tarjan…… 1 /************************************************************** 2 Problem: 2938 3 User: Tunix 4 Language: C++ 5 Result: Acce

BZOJ2938: [Poi2000]病毒

传送门 AC自动机上的各种处理一直让我很迷.一个主要懵逼的点是不清楚对于不存在的字母所对应的方案如何处理.做了两道题大概比较清楚了. 其实对于不存在的字母节点不需要特殊的处理.因为如果累加方案的话,其方案会自动累加到$root$节点.而其fail指针也会自动指向自己. 另外这道题的判环参考了黄学长的代码,类似于一个简化版的tarjan. //BZOJ 2938 //by Cydiater //2016.10.18 #include <iostream> #include <cstdio&

AC自动机及KMP练习

好久都没敲过KMP和AC自动机了.以前只会敲个kuangbin牌板子套题.现在重新写了自己的板子加深了印象.并且刷了一些题来增加自己的理解. KMP网上教程很多,但我的建议还是先看AC自动机(Trie图)的构造后再去理解.板子的话大家大同小异. 而AC自动机的构造则是推荐王贇的<Trie图的构建.活用与改进>. 前面的备用知识则是字典树.推荐董华星的<浅析字母树在信息学竞赛中的应用>.董聚聚不仅仅是介绍了字典树,包括一些常见的应用也有论述,介绍的挺详细的. 接下来就是刷题的部分了.

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比