[HDOJ2222]Keywords Search(AC自动机)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222

题意:求字典中所有模式串各出现了多少次。

建立AC自动机,查询的时候首先跳过所有cur->next[index]为NULL的情况,再跳过cur是root的情况。因为root不存任何信息。

过滤完上述情况,那么当前匹配串上的index位置必然在trie上出现过,那么就沿着当前点的fail一路找上去。因为trie某节点的fail指针要么指向root,要么指向与当前字符相同的节点。接着记下每个点的cnt值,不要忘记置零防止重复统计。

时隔多年(什么多年啊喂)重拾AC自动机,终于彻彻底底弄明白了。感恩的心。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 inline int GetId(char c) {
  5     return c - ‘a‘;
  6 }
  7 typedef class Node {
  8 public:
  9     Node *next[26];
 10     Node *fail;
 11     int cnt;
 12     Node() {
 13         memset(next, 0, sizeof(next));
 14         fail = NULL;
 15         cnt = 0;
 16     }
 17 }Node;
 18 class AC_Automation {
 19 public:
 20     Node *root;
 21     queue <Node*> q;
 22     AC_Automation() {
 23         root = new Node;
 24         while(!q.empty()) q.pop();
 25     }
 26     void insert(string s) {
 27         Node *cur = root;
 28         int len = s.length();
 29         for(int i = 0; i < len; i++) {
 30             int index = GetId(s[i]);
 31             if(cur->next[index] == NULL) {
 32                 cur->next[index] = new Node;
 33             }
 34             cur = cur->next[index];
 35         }
 36         cur->cnt++;
 37     }
 38     void BuildAC() {
 39         Node *cur,*tmp;
 40         q.push(root);
 41         while(!q.empty()) {
 42             cur = q.front();
 43             q.pop();
 44             for(int i = 0; i < 26; i++) {
 45                 if(cur->next[i]) {
 46                     if(cur == root) {
 47                         cur->next[i]->fail = root;
 48                     }
 49                     else {
 50                         tmp = cur->fail;
 51                         while(tmp != NULL) {
 52                             if(tmp->next[i]) {
 53                                 cur->next[i]->fail = tmp->next[i];
 54                                 break;
 55                             }
 56                             tmp = tmp->fail;
 57                         }
 58                         if(tmp == NULL) {
 59                             cur->next[i]->fail = root;
 60                         }
 61                     }
 62                     q.push(cur->next[i]);
 63                 }
 64             }
 65         }
 66     }
 67     int query(string s) {
 68         Node *cur = root,*tmp;
 69         int len = s.length();
 70         int ret = 0;
 71         for(int i = 0; i < len; i++) {
 72             int index = GetId(s[i]);
 73             while(cur->next[index] == NULL && cur != root) {
 74                 cur = cur->fail;
 75             }
 76             cur = cur->next[index];
 77             if(cur == NULL) {
 78                 cur = root;
 79                 continue;
 80             }
 81             tmp = cur;
 82             while(tmp != root) {
 83                 ret += tmp->cnt;
 84                 tmp->cnt = 0;
 85                 tmp = tmp->fail;
 86             }
 87         }
 88         return ret;
 89     }
 90 };
 91 char pat[52], tar[2000005];
 92 int n;
 93
 94 int main() {
 95     // freopen("in", "r", stdin);
 96     int T;
 97     scanf("%d", &T);
 98     while(T--) {
 99         scanf("%d", &n);
100         AC_Automation ac;
101         for(int i = 0; i < n; i++) {
102             scanf("%s", pat);
103             ac.insert(pat);
104         }
105         ac.BuildAC();
106         scanf("%s", tar);
107         cout << ac.query(tar) << endl;
108     }
109     return 0;
110 }
时间: 2024-08-08 09:29:22

[HDOJ2222]Keywords Search(AC自动机)的相关文章

HDU 2222 Keywords Search AC自动机入门题

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

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

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

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

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)第一步还是比较好理解的 根是虚根,边代表字母,那么根到终止节点的路径就是一个字符串,这样对于前缀相同的字符串我们就可以省下存公共前缀的空间. 加入一个模式

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]结尾的该结点是否为关键字最后一个结点,重复进行

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

原题大意:原题链接 先给定T个单词,然后给定一个字符串,查询该字符串中包含多少个给定的单词 解题思路:AC自动机模板题 参考链接:哔哩哔哩算法讲堂 WA版本 注意:因为输入的单词可能有重复,那么Insert()函数中p->id=id;语句中p->id会被覆盖,在Query()函数中会一次性全部被清零,导致不能查询重复单词,以至于结果res错误. #include<queue> #include<cstdio> #include<cstring> using