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

题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串。其中模式串可以重复。问有多少文本串在模式串中出现过。(对于相同的模式串次数仍然累加)

思路:ac自动机裸题;

KMP是先将文本串进行匹配得到失配边f[];但是并不适用于文本串较长,模式串较多的情况。因为每次查询的时间复杂度为O(n+m).n,m分别为文本串和模式串的长度;

ac自动机就是建立在Trie上,用bfs得到适配边的一个逆向过程;

即将所有的模式串建立一个状态转移,之后直接匹配文本串即可;

关键:每次看的是文本串中的当前点的后缀是那个模式串的前缀,(BFS中获得f[]的关键思想)或者就是那个模式串。之后递归打印即可;

  1. // 358MS 32704K
    #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<string.h>
  5. #include<algorithm>
  6. #include<vector>
  7. #include<cmath>
  8. #include<stdlib.h>
  9. #include<time.h>
  10. #include<stack>
  11. #include<set>
  12. #include<map>
  13. #include<queue>
  14. using namespace std;
  15. #define rep0(i,l,r) for(int i = (l);i < (r);i++)
  16. #define rep1(i,l,r) for(int i = (l);i <= (r);i++)
  17. #define rep_0(i,r,l) for(int i = (r);i > (l);i--)
  18. #define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
  19. #define MS0(a) memset(a,0,sizeof(a))
  20. #define MS1(a) memset(a,-1,sizeof(a))
  21. #define MSi(a) memset(a,0x3f,sizeof(a))
  22. #define inf 0x3f3f3f3f
  23. #define lson l, m, rt << 1
  24. #define rson m+1, r, rt << 1|1
  25. typedef pair<int,int> PII;
  26. #define A first
  27. #define B second
  28. #define MK make_pair
  29. typedef __int64 ll;
  30. template<typename T>
  31. void read1(T &m)
  32. {
  33. T x=,f=;char ch=getchar();
  34. while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
  35. while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
  36. m = x*f;
  37. }
  38. template<typename T>
  39. void read2(T &a,T &b){read1(a);read1(b);}
  40. template<typename T>
  41. void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);}
  42. template<typename T>
  43. void out(T a)
  44. {
  45. if(a>) out(a/);
  46. putchar(a%+'');
  47. }
  48. int T,kase = ,i,j,k,n,m;
  49. const int sigma_size = ;
  50. const int maxn = *+;
  51. struct Aho_Corasick{
  52. int ch[maxn][sigma_size];
  53. int val[maxn],f[maxn],last[maxn],cnt[maxn];
  54. int sz;
  55. map<string,int> ms;
  56. Aho_Corasick(){}
  57. void init(){sz = ; MS0(ch[]);MS0(cnt);ms.clear();}
  58. void Insert(char *s,int v){
  59. int u = ,n = strlen(s);
  60. for(int i = ;i < n;i++){
  61. int c = s[i] -'a';
  62. if(!ch[u][c]){
  63. MS0(ch[sz]);
  64. val[sz] = ;
  65. ch[u][c] = sz++;
  66. }
  67. u = ch[u][c];
  68. }
  69. val[u] = v;
  70. ms[string(s)] = v;//使用map来对应重复出现的字符串;竟然可以强转..
  71. }
  72. void getFail(){
  73. queue<int> q;
  74. f[] = ;
  75. //初始化队列
  76. for(int c = ;c < sigma_size;c++){
  77. int u = ch[][c];
  78. if(u) { f[u] = ; q.push(u); last[u] = ;}
  79. }
  80. while(!q.empty()){
  81. int r = q.front();q.pop();
  82. for(int c = ;c < sigma_size;c++){
  83. int u = ch[r][c];
  84. if(!u) {ch[r][c] = ch[f[r]][c]; continue;}//实现压缩
  85. q.push(u);
  86. int v = f[r];
  87. while(v && !ch[v][c]) v = f[v];
  88. f[u] = ch[v][c];
  89. last[u] = val[f[u]]?f[u]:last[f[u]];
  90. }
  91. }
  92. }
  93. //从文本串中找模板;
  94. void Find(char *T){
  95. int n = strlen(T);
  96. int j = ;
  97. for(int i = ;i < n;i++){
  98. int c = T[i] - 'a';
  99. j = ch[j][c];//直接查找即可;
  100. if(val[j]) print(j);
  101. else if(last[j]) print(last[j]);
  102. }
  103. }
  104. void print(int j){
  105. if(j) {
  106. cnt[val[j]]++;
  107. print(last[j]);
  108. }
  109. }
  110. }ac;
  111. char p[][];
  112. char text[];
  113. int main()
  114. {
  115. read1(T);
  116. while(T--){
  117. ac.init();
  118. read1(n);
  119. rep1(i,,n){
  120. scanf("%s",p[i]);
  121. ac.Insert(p[i],i);
  122. }
  123. ac.getFail();
  124. scanf("%s",text);
  125. ac.Find(text);
  126. int ans = ;
  127. rep1(i,,n){
  128. if(ac.cnt[ac.ms[string(p[i])]]) ans++;
  129. }
  130. out(ans);
  131. puts("");
  132. }
  133. return ;
  134. }

hdu 2222 Keywords Search ac自动机入门的更多相关文章

  1. hdu 2222 Keywords Search——AC自动机

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2222 第一道AC自动机! T了无数边后终于知道原来它是把若干询问串建一个自动机,把模式串放在上面跑:而且只 ...

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

    学习AC自动机请戳这里:大神blog........ 自动机的模板: #include <iostream> #include <algorithm> #include < ...

  3. HDU 2222 Keywords Search (AC自动机)

    题意:就是求目标串中出现了几个模式串. 思路:用int型的end数组记录出现,AC自动机即可. #include<iostream> #include<cstdio> #inc ...

  4. hdu 2222 Keywords Search ac自动机模板

    题目链接 先整理一发ac自动机模板.. #include <iostream> #include <vector> #include <cstdio> #inclu ...

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

    <题目链接> 题目大意: 给你一些单词,和一个字符串,问你这个字符串中含有多少个上面的单词. 解题分析: 这是多模匹配问题,如果用KMP的话,对每一个单词,都跑一遍KMP,那么当单词数量非 ...

  6. hdu2222 KeyWords Search AC自动机入门题

    /** 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:题意:给定N(N <= 10000)个长度不大于50的模式串,再给定一个长度为L ...

  7. hdu 2222 Keywords Search - Aho-Corasick自动机

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submissio ...

  8. hdoj 2222 Keywords Search(AC自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 思路分析:该问题为多模式匹配问题,使用AC自动机解决:需要注意的问题是如何统计该待查询的字符串包 ...

  9. hdu 2222 Keywords Search ac自己主动机

    点击打开链接题目链接 Keywords Search Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Ja ...

随机推荐

  1. 利用DBExportDoc V1.0 For MySQL自动生成数据库表结构文档

    对于DBA或开发来说,如何规范化你的数据库表结构文档是灰常之重要的一件事情.但是当你的库,你的表排山倒海滴多的时候,你就会很头疼了. 推荐一款工具DBExportDoc V1.0 For MySQL( ...

  2. Mailing API

    Mailing API Configuration Basic Usage Embedding Inline Attachments Mail & Local Development Work ...

  3. CSS 之 清除 float 常用的方法

    大多数前端使用.clearfix:after{ .....}  和 .clearit{....}的组合来清除浮动. 前端开发经常用到浮动 float:left; float:right; 有浮动就需要 ...

  4. linux 多核

    posix threading programming beej's guide to unix ipc the gnu c library: virtual memory allocation an ...

  5. 如何在ios手机端的Safari浏览器 中“查看网页源代码”

    在这里给大家分享一个很简单的用苹果手机无需越狱就可以查看网页源代码的方法,不过这个方法只用于苹果手机自带的Safari浏览器 随便添加一个safari 书签 (用于一会改为查看源码功能书签)进入书签 ...

  6. SignalR 跨域设置

    参考文章:http://www.cnblogs.com/nywd/p/3691813.html 上一节,已经实现了,当前域内的通信,这一节中,介绍一下跨域的即时通信,既然要做,我们肯定要把这个推送及聊 ...

  7. C#学习笔记2:Iframe框架、MD5加密

    1.static void Main()的问题. static void Main(){……//代码}static void Main(string[] args){……//代码}两者的不同点?str ...

  8. java--简单排序算法

    1.冒泡排序 排序原理: 过程简单,首先将第一个记录的关键字和第二个记录的关键字进行比较,若为逆序,则将两个记录交换,然后比较第二个记录与第三个记录得关键字.以此类推,直至第n-1个记录和第n个记录的 ...

  9. 陷阱~SQL全表扫描与聚集索引扫描

    SqlServer中在查询时,我们为了优化性能,通常会为where条件的字段建立索引,如果条件比较固定还会建立组合索引,接下来,我们来看一下索引与查询的相关知识及相关陷阱. SQL表自动为主键加聚集索 ...

  10. 浅谈JAVA集合框架(转载)_常用的Vector和HashMap

    原作者滴着:http://www.cnblogs.com/eflylab/archive/2007/01/20/625237.html Java提供了数种持有对象的方式,包括语言内置的Array,还有 ...