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

学习出:https://bestsort.cn/2019/04/28/402/

主要是fail的建立。在跳的过程就是不断跳fail,而不是跳到一个fail再往下!!

  1. #include<iostream>
  2. #include<queue>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<string>
  6. using namespace std;
  7. typedef long long ll;
  8. const int M=2e6+;
  9.  
  10. int trie[M][]; //字典树
  11. int cntword[M]; //记录该单词出现次数
  12. int fail[M]; //失败时的回溯指针
  13. int cnt=;
  14.  
  15. void insert(string s){
  16. int root = ;
  17. for(int i=;i<s.size();i++){
  18. int next = s[i] - 'a';
  19. if(!trie[root][next])
  20. trie[root][next] = ++cnt;
  21. root = trie[root][next];
  22. }
  23. cntword[root]++; //当前节点单词数+1
  24. }
  25. void getfail(){
  26. queue <int>q;
  27. for(int i=;i<;i++){ //将第二层所有出现了的字母扔进队列
  28. if(trie[][i]){
  29. fail[trie[][i]] = ;
  30. q.push(trie[][i]);
  31. }
  32. }
  33.  
  34. //fail[now] ->当前节点now的失败指针指向的地方
  35. ////tire[now][i] -> 下一个字母为i+'a'的节点的下标为tire[now][i]
  36. while(!q.empty()){
  37. int now = q.front();
  38. q.pop();
  39.  
  40. for(int i=;i<;i++){ //查询26个字母
  41. if(trie[now][i]){
  42. //如果有这个子节点为字母i+'a',则
  43. //让这个节点的失败指针指向(((他父亲节点)的失败指针所指向的那个节点)的下一个节点)
  44. //有点绕,为了方便理解特意加了括号
  45.  
  46. fail[trie[now][i]] = trie[fail[now]][i];
  47. q.push(trie[now][i]);
  48. }
  49. else//否则就让当前节点的这个子节点
  50. //指向当前节点fail指针的这个子节点
  51. trie[now][i] = trie[fail[now]][i];
  52. }
  53. }
  54. }
  55.  
  56. int query(string s){
  57. int now = ,ans = ;
  58. for(int i=;i<s.size();i++){ //遍历文本串
  59. now = trie[now][s[i]-'a']; //从s[i]点开始寻找
  60. for(int j=now;j && cntword[j]!=-;j=fail[j]){
  61. //一直向下寻找,直到匹配失败(失败指针指向根或者当前节点已找过).
  62. ans += cntword[j];
  63. cntword[j] = -; //将遍历国后的节点标记,防止重复计算
  64. }
  65. }
  66. return ans;
  67. }
  68.  
  69. void Clear(){
  70. for(int i=;i<=cnt;i++){
  71. for(int j=;j<;j++)
  72. trie[i][j]=;
  73. cntword[i]=;
  74. fail[i]=;
  75. }
  76.  
  77. }
  78. int n,t;
  79. int main(){
  80.  
  81. ios::sync_with_stdio(false);
  82. cin.tie();
  83. cin>>t;
  84. while(t--){
  85. cin>>n;
  86. string s;
  87. for(int i=;i<=n;i++){
  88.  
  89. cin>>s;
  90. insert(s);
  91. }
  92. fail[]=;
  93. getfail();
  94. cin>>s;
  95. cout<<query(s)<<endl;
  96. Clear();
  97. }
  98. return ;
  99. }
  100.  
  101. /*
  102. 5
  103. ash
  104. shex
  105. bcd
  106. sha
  107. sh
  108. ashe
  109.  
  110. 2
  111. */

hdu2222 (AC自动机模板)的更多相关文章

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

    AC自动机模板,注意!ch,Fail,lab数组的大小不是n而是节点个数,需要认真计算! #include <iostream> #include <algorithm> #i ...

  2. Keywords Search HDU2222 AC自动机模板题

    ac自动机说起来很复杂,其实和kmp是一样的思路,都是寻找相同前后缀,减少跳的次数.只要理解了kmp是怎么求next数组的,ac自动机bfs甚至比knp还好写. 这里大致说一下kmp求next数组的方 ...

  3. hdu2222(ac自动机模板)

    #include<iostream> #include<cmath> #include<cstdio> #include<cstring> #inclu ...

  4. Hdu 5384 Danganronpa (AC自动机模板)

    题目链接: Hdu 5384 Danganronpa 题目描述: 给出n个目标串Ai,m个模式串Bj,问每个目标串中m个模式串出现的次数总和为多少? 解题思路: 与Hdu 2222  Keywords ...

  5. HDU 2222 AC自动机模板题

    题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...

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

    多模匹配 题目大意:给定很多个字串A,B,C,D,E....,然后再给你目标串str字串,看目标串中出现多少个给定的字串. 经典AC自动机模板题,不多说. #include <iostream& ...

  7. HDU 3065 (AC自动机模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...

  8. HDU 2896 (AC自动机模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串 ...

  9. HDU 2222(AC自动机模板题)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题 ...

  10. HDU2222 (AC自动机)

    AC自动机模板题. 被卡内存了 死活A不掉.. AC自动机参考教程: http://www.cppblog.com/menjitianya/archive/2014/07/10/207604.html ...

随机推荐

  1. 面试题(7)之 leetcode-003

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&quo ...

  2. Invalid bound statement (not found): com.xxxx.dao.other.LoginDao.getUser"

    原来是能正常运行的,后想把登录相关的调整一下目录,对应登录的文件都调整到了other下边,启动服务,请求时报错: Invalid bound statement (not found): com.xx ...

  3. VUE.js入门学习(5)- 插槽和作用域插槽

    插槽: (1)用法 以前的写法:如果内容很多的话,就很烂了- 插槽写法:(PS:组建名不能用保留关键字) (2)具名插槽 (3)作用域插槽 必须template开始和结尾,这个插槽要声明我从子组建接收 ...

  4. 关于mysql/apache/nginx的配置文件配置

    2015.5.12 mysql中可以通过函数查看用户列表/查看当前用户以及删除用户,方法百度之,忘了 /etc/php5/fpm/php.ini memory_limit修改之前为128M apach ...

  5. 工程日记之ChildLost(2) :如何编写一个多线程的程序

    Dispatch Dispatch结合语言特性,运行时,和系统的特点,提供了系统的,全面的高层次API来提升多核多线程编程的能力. Dispatch会自动的根据CPU的使用情况,创建线程来执行任务,并 ...

  6. SpingBoot项目搭建(详细)

    SpingBoot (原创:黑小子-余) springboot官网:->点击<- spring官网:->点击<- 一.SpringBoot简介 Spring Boot是由Piv ...

  7. 程序员必备:详解XSS和CSRF

    做开发的小伙伴想必都不陌生XSS 和 CSRF,但也有一些刚接触的朋友还不是很清楚,今天就给大家详解下XSS和CSRF! 一.XSS xss,即 Cross Site Script,中翻译是跨站脚本攻 ...

  8. 十六进制转化二进制[c]

    #include<stdio.h> #include<string.h> #include<stdlib.h> int hex2dec(char c) { ; // ...

  9. 乳草的侵占(BFS)

    armer John一直努力让他的草地充满鲜美多汁的而又健康的牧草.可惜天不从人愿,他在植物大战人类中败下阵来.邪恶的乳草已经在他的农场的西北部份占领了一片立足之地. 草地像往常一样,被分割成一个高度 ...

  10. Mybatis学习——Mybatis核心配置

    MyBatis的核心配置 在使用MyBatis框架时,设计两个核心的d对象:SqlSessionFactory和SqlSession. SqlsessionFactory SqlSessionFact ...