hdu2222(ac自动机模板)

先推荐两篇写的很好的ac自动机blog:

http://blog.csdn.net/creatorx/article/details/71100840

http://blog.csdn.net/niushuai666/article/details/7002823

正题

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

题意: 给出 n 个模式串以及一个 主串, 问有多少个模式串在主串中出现过

思路: ac自动机模板题

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <queue>
 5 using namespace std;
 6
 7 const int MAXN = 5e5 + 10;
 8
 9 struct Trie{
10     int next[MAXN][26], fail[MAXN], end[MAXN];
11     int root, L;
12     int newnode(){//初始化字典树节点
13         for(int i = 0; i < 26; i++){
14             next[L][i] = -1;
15         }
16         end[L++] = 0;
17         return L - 1;
18     }
19     void init(){//初始化字典树根节点
20         L = 0;
21         root = newnode();
22     }
23     void insert(char buf[]){//往字典树中插入一个单词
24         int len = strlen(buf);
25         int now = root;
26         for(int i = 0; i < len; i++){
27             if(next[now][buf[i] - ‘a‘] == -1) next[now][buf[i] - ‘a‘] = newnode();
28             now = next[now][buf[i] - ‘a‘];
29         }
30         end[now]++;
31     }
32     void build(){ //构造fail数组
33         queue<int> Q;
34         fail[root] = root;
35         for(int i = 0; i < 26; i++){
36             if(next[root][i] == -1) next[root][i] = root;
37             else{
38                 fail[next[root][i]] = root;
39                 Q.push(next[root][i]);
40             }
41         }
42         while(!Q.empty()){
43             int now = Q.front();
44             Q.pop();
45             for(int i = 0; i < 26; i++)
46             if(next[now][i] == -1) next[now][i] = next[fail[now]][i];
47             else{
48                 fail[next[now][i]] = next[fail[now]][i];
49                 Q.push(next[now][i]);
50             }
51         }
52     }
53     int query(char buf[]){
54         int len = strlen(buf);
55         int now = root;
56         int res = 0;
57         for(int i = 0; i < len; i++){
58             now = next[now][buf[i] - ‘a‘];
59             int temp = now;
60             while(temp != root){
61                 res += end[temp];
62                 end[temp] = 0; // 每个模式串只算一次,所以清0
63                 temp = fail[temp];
64             }
65         }
66         return res;
67     }
68     void debug(){
69         for(int i = 0; i < L; i++){
70             printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
71             for(int j = 0; j < 26; j++){
72                 printf("%2d",next[i][j]);
73             }
74             printf("]\n");
75         }
76     }
77 };
78
79 Trie ac;
80 char buf[MAXN << 1];
81
82 int main(void){
83     int t, n;
84     scanf("%d", &t);
85     while(t--){
86         ac.init();
87         scanf("%d", &n);
88         for(int i = 0; i < n; i++){
89             scanf("%s", buf);
90             ac.insert(buf);
91         }
92         ac.build();
93         scanf("%s", buf);
94         printf("%d\n", ac.query(buf));
95     }
96     return 0;
97 }

时间: 2024-08-04 10:17:22

hdu2222(ac自动机模板)的相关文章

[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>

Keywords Search HDU2222 AC自动机模板题

ac自动机说起来很复杂,其实和kmp是一样的思路,都是寻找相同前后缀,减少跳的次数.只要理解了kmp是怎么求next数组的,ac自动机bfs甚至比knp还好写. 这里大致说一下kmp求next数组的方法吧,假设现在要求第c个字符的next值(假设这个c很大,这样画图出来比较清晰方便理解),因为遍历过程中我们已经知道了第c-1个字符的next为x(假设比c小很多),即next[c-1] = x.那就代表我们知道了a[1]-a[x]这一段和a[c-1-x]-a[c-1]这一段是相等的对吧. 那么现在

hdu2222 AC自动机-给定串中出现了几个模式串

http://acm.hdu.edu.cn/showproblem.php?pid=2222 Problem Description In the modern time, Search engine came into the life of everybody like Google, Baidu, etc. Wiskey also wants to bring this feature to his image retrieval system. Every image have a lo

LA 4670 出现次数最多的子串 (AC自动机模板题)

Dominating Patterns Time Limit:3000MS   Memory Limit:Unknown   64bit IO Format:%lld & %llu [Submit]  [Go Back]  [Status] Description The archaeologists are going to decipher a very mysterious ``language". Now, they know many language patterns; ea

hdu5384 AC自动机模板题,统计模式串在给定串中出现的个数

http://acm.hdu.edu.cn/showproblem.php?pid=5384 Problem Description Danganronpa is a video game franchise created and developed by Spike Chunsoft, the series' name is compounded from the Japanese words for "bullet" (dangan) and "refutation&q

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 {

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

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

HDU 2222(AC自动机模板题)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题思路: AC自动机模板题. 一开始使用LRJ的坑爹静态模板,不支持重复的模式串. 在做AC自动机+DP的时候,扒了zcwwzdjn大神的动态优化(失配指向root)写法,以及借鉴了网上的AC自动机模板, 搞出了这么一个支持重复串的模板. #include "cstdio" #include

HDU 2222 Keyword Search AC自动机模板

#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <io