hdu2222 Keywords Search(AC自动机初步)

题目大意:

  给出多个模式串和一个主串,求多少个模式串在主串中出现过。



  传送门

这是一道AC自动机的模板题。

在学习AC自动机之前,首先要学习WA自动机、TLE自动机和MLE自动机(雾

AC自动机是一种多模式串匹配算法。

AC自动机概述:

  *fail指针:指向失配时的匹配节点;

  1)构建字典树

  2)初始化fail指针:

    一条$fail$指针链可以理解为一个串连所有后缀相同的字符串的链表,并且所有链表的末端都指向trie的根。我们定义沿着节点$v$的$fail$指针走到根部的路径为v的trie链表

    虚线为$fail$指针,红色节点为AC-DFA的接收态。

    使用BFS构造fail指针:初始化队列为树根。对于trie上的每个非叶子节点$u$的孩子$v$,我们沿着其fail链表向上走,直到某个节点的孩子$x=v$,则$v->fail=x$。将$v$加入队列。

    特别的,对于$p->nxt[i]==NULL$的节点,令$p->nxt[i]=p->fail->nxt[i]$

  3)由于初始化$fail$指针的时候,令$p->nxt[i]=p->fail->nxt[i]$,所以现在的trie树变成了一个trie图,所有节点的$nxt$指针都不为空。我们按照主串,沿着相应的路径向走trie图,每访问一个节点就遍历该节点的$fail$链表并计数。

代码:

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cctype>
 6 #define foru(i,x,y) for(int i=x;i<=y;i++)
 7 const int N=1e6+10;
 8
 9 struct trie{
10     trie *nxt[26];
11     trie *fail;
12     int v;
13     void init(){v=0;foru(i,0,25)nxt[i]=NULL;fail=NULL;}
14 };
15 trie *r,*q[600000];
16 int T,n;
17 char ch[N];
18 void add(char *s){//建trie
19     trie *k=r,*p;
20     int l=strlen(s);
21     foru(i,0,l-1){
22         int id=s[i]-‘a‘;
23         if(!k->nxt[id]){
24             p=(trie*)malloc(sizeof(trie));
25             p->init();
26             k->nxt[id]=p;
27             k=p;
28         }else{
29             k=k->nxt[id];
30         }
31     }
32     k->v++;//标记为接收态
33 }
34
35 void setfail(){
36     trie *k;
37     int s=1,t=0;
38     q[++t]=r;
39     while(s<=t){
40         k=q[s++];
41         foru(i,0,25){
42             if(k->nxt[i]){
43                 trie *p=k->fail;
44                 while(p&&!p->nxt[i])p=p->fail;//寻找上一个相同后缀的字符串
45                 k->nxt[i]->fail=(!p?r:p->nxt[i]);//不存在则指向trie根
46                 q[++t]=k->nxt[i];
47             }else
48                 k->nxt[i]=(k==r?r:k->fail->nxt[i]);
49         }
50     }
51 }
52
53 int find(char *s){
54     trie *k=r,*p;int ret=0;
55     int l=strlen(s);
56     foru(i,0,l-1){
57         int id=s[i]-‘a‘;
58         k=k->nxt[id];
59         p=k;
60         while(p){//遍历fail链
61             ret+=p->v;
62             p->v=0;//避免重复计数
63             p=p->fail;
64         }
65     }
66     return ret;
67 }
68
69 int main(){
70     scanf("%d",&T);
71     while(T--){
72         r=(trie*)malloc(sizeof(trie));
73         r->init();
74         scanf("%d",&n);
75         foru(i,1,n){
76             scanf("%s",ch);
77             add(ch);
78         }
79         setfail();
80         scanf("%s",ch);
81         printf("%d\n",find(ch));
82     }
83 }
时间: 2024-11-02 08:21:42

hdu2222 Keywords Search(AC自动机初步)的相关文章

hdu2222 Keywords Search ac自动机

地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 题目: Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 56558    Accepted Submission(s): 18493 Problem Description In the mo

hdu2222 Keywords Search &amp; AC自动机学习小结

传送门:http://http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路:AC自动机入门题,直接上AC自动机即可. 对于构建AC自动机,我们要做的只有三件事: 1)构建字典树 2)构建失败指针 3)构建trie图(这道题好像不做这一步也能A...但是这一步不做是会被卡成O(n^2)的...) 1)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

HDU 2222 Keywords Search AC自动机入门题

单词统计的题目,给出一些单词,统计有多少单词在一个文本中出现,最经典的入门题了. AC自动机的基础: 1 Trie, 以这个数据结构为基础的,不过增加一个fail指针和构造fail的函数 2 KMP,不是直接运用KMP,而是需要KMP的思想,KMP思想都没有的话,理解这个算法会更加吃力的. 注意本题的单词会有重复出现的,一个单词只能统计一次. 搜索了一下网上的题解,发现好多代码都是一大抄的啊,⊙﹏⊙b汗. 本博客的乃是原创代码,代码风格也是差不多固定的,转载请注明出处:http://blog.c

[hdu2222] [AC自动机模板] Keywords Search [AC自动机]

AC自动机模板,注意!ch,Fail,lab数组的大小不是n而是节点个数,需要认真计算! 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdlib> 8 #include <queue>

HDU 2222 Keywords Search AC自动机

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67122    Accepted Submission(s): 22584 Problem Description In the modern time, Search engine came into the life of everybody lik

hdu 2222 Keywords Search(ac自动机入门题)

1 /************************************************************ 2 题目: Keywords Search(hdu 2222) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 4 算法: ac自动机 5 算法思想: 多个字符串匹配,也就是相当于多个kmp 6 ***********************************************************

HDU 2222 Keywords Search (AC自动机入门 模板)

AC自动机入门 Aho-Corasick automaton,该算法在1975年产生于贝尔实验室,是著名的多模匹配算法之一.学习AC自动机之前得先有Trie树和KMP模式匹配算法的基础. AC自动机算法分为3步:1.构造一棵tire树  2.构造失败指针  3.进行模式匹配 AC自动机的优化:Trie图 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other

HDU 2222 Keywords Search (AC自动机模板题)

Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 67950    Accepted Submission(s): 22882 Problem Description In the modern time, Search engine came into the life of everybody lik

Match:Keywords Search(AC自动机模板)(HDU 2222)

多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. 1 #include <iostream> 2 #include <algorithm> 3 #include <functional> 4 #include <string.h> 5 #define MAX 26 6 7 using namespace std; 8 9 struct node 10 {

hdoj 2222 Keywords Search(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路分析:该问题为多模式匹配问题,使用AC自动机解决:需要注意的问题是如何统计该待查询的字符串包含的关键字: 假设待查找的字符串为str[0..n],则str[i…j]可能为某一个关键字:假设当前正在匹配字符str[k],则以str[i..k]为关键字的所有可能 可能的关键字的最后一个字符为str[k],使用fail指针进行跳转并判断以str[k]结尾的该结点是否为关键字最后一个结点,重复进行