最近正在学AC自动机,按照惯例需要刷一套kuangbin的AC自动机专题巩固

在网上看过很多模板,感觉kuangbin大神的模板最为简洁,于是就选择了用kuangbin大神的模板。

AC自动机其实就是字典树和KMP的结合,然后去思考一下KMP的原理,然后就是在字典树上实现KMP

这里最重要的思想可能就是fail的思想,就像KMP一样,匹配失败后,有一个next的数组去回溯(最长公共前缀后缀)

如何理解了KMP的话,感觉这个不会很难理解,字典树是一个非常简单的东西就不用讲了吧。

HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430

这是我总结出来的AC自动机解决的第一类问题,求文本串和模式串的关系(模式串出现几次之类的问题)

我把这几题放一起写了算了,因为套路一样随便改一下就好了

Keywords Search HDU - 2222

询问有多少个模式串出现在了文本串里面。

将模式串插入Trie树中,然后直接查询就好了。

  1. #include <set>
  2. #include <map>
  3. #include <stack>
  4. #include <queue>
  5. #include <cmath>
  6. #include <cstdio>
  7. #include <string>
  8. #include <vector>
  9. #include <time.h>
  10. #include <cstring>
  11. #include <iostream>
  12. #include <algorithm>
  13. #include <unordered_map>
  14.  
  15. #define pi acos(-1.0)
  16. #define eps 1e-9
  17. #define fi first
  18. #define se second
  19. #define rtl rt<<1
  20. #define rtr rt<<1|1
  21. #define bug printf("******\n")
  22. #define mem(a, b) memset(a,b,sizeof(a))
  23. #define name2str(x) #x
  24. #define fuck(x) cout<<#x" = "<<x<<endl
  25. #define sf(n) scanf("%d", &n)
  26. #define sff(a, b) scanf("%d %d", &a, &b)
  27. #define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
  28. #define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
  29. #define pf printf
  30. #define FIN freopen("data.txt","r",stdin)
  31. #define gcd(a, b) __gcd(a,b)
  32. #define lowbit(x) x&-x
  33. #define IO iOS::sync_with_stdio(false)
  34.  
  35. using namespace std;
  36. typedef long long LL;
  37. typedef unsigned long long ULL;
  38. const int maxn = 1e6 + ;
  39. const int maxm = 8e6 + ;
  40. const int INF = 0x3f3f3f3f;
  41. const int mod = 1e9 + ;
  42.  
  43. struct Aho_Corasick {
  44. int next[][], fail[], End[];
  45. int root, cnt;
  46.  
  47. int newnode() {
  48. for (int i = ; i < ; i++) next[cnt][i] = -;
  49. End[cnt++] = ;
  50. return cnt - ;
  51. }
  52.  
  53. void init() {
  54. cnt = ;
  55. root = newnode();
  56. }
  57.  
  58. void insert(char buf[]) {
  59. int len = strlen(buf);
  60. int now = root;
  61. for (int i = ; i < len; i++) {
  62. if (next[now][buf[i] - 'a'] == -) next[now][buf[i] - 'a'] = newnode();
  63. now = next[now][buf[i] - 'a'];
  64. }
  65. End[now]++;
  66. }
  67.  
  68. void build() {
  69. queue<int> Q;
  70. fail[root] = root;
  71. for (int i = ; i < ; i++)
  72. if (next[root][i] == -) next[root][i] = root;
  73. else {
  74. fail[next[root][i]] = root;
  75. Q.push(next[root][i]);
  76. }
  77. while (!Q.empty()) {
  78. int now = Q.front();
  79. Q.pop();
  80. for (int i = ; i < ; i++)
  81. if (next[now][i] == -) next[now][i] = next[fail[now]][i];
  82. else {
  83. fail[next[now][i]] = next[fail[now]][i];
  84. Q.push(next[now][i]);
  85. }
  86. }
  87. }
  88.  
  89. int query(char buf[]) {
  90. int len = strlen(buf);
  91. int now = root;
  92. int res = ;
  93. for (int i = ; i < len; i++) {
  94. now = next[now][buf[i] - 'a'];
  95. int temp = now;
  96. while (temp != root) {
  97. res += End[temp];
  98. End[temp] = ;
  99. temp = fail[temp];
  100. }
  101. }
  102. return res;
  103. }
  104.  
  105. void debug() {
  106. for (int i = ; i < cnt; i++) {
  107. printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
  108. for (int j = ; j < ; j++) printf("%2d", next[i][j]);
  109. printf("]\n");
  110. }
  111. }
  112. }ac;
  113.  
  114. char buf[];
  115. int T,n;
  116. int main() {
  117. sf(T);
  118. while(T--){
  119. sf(n);
  120. ac.init();
  121. for (int i = ; i < n; ++i) {
  122. scanf("%s",buf);
  123. ac.insert(buf);
  124. }
  125. scanf("%s",buf);
  126. ac.build();
  127. printf("%d\n",ac.query(buf));
  128. }
  129. return ;
  130. }

病毒侵袭 HDU - 2896

给出n个模式串,对m个串进行匹配,输出匹配的模式串的编号,以及总共多少个串可以匹配。

字符总数有128,而且编号要排序。

  1. #include <set>
  2. #include <map>
  3. #include <stack>
  4. #include <queue>
  5. #include <cmath>
  6. #include <cstdio>
  7. #include <string>
  8. #include <vector>
  9. #include <time.h>
  10. #include <cstring>
  11. #include <iostream>
  12. #include <algorithm>
  13. #include <unordered_map>
  14.  
  15. #define pi acos(-1.0)
  16. #define eps 1e-9
  17. #define fi first
  18. #define se second
  19. #define rtl rt<<1
  20. #define rtr rt<<1|1
  21. #define bug printf("******\n")
  22. #define mem(a, b) memset(a,b,sizeof(a))
  23. #define name2str(x) #x
  24. #define fuck(x) cout<<#x" = "<<x<<endl
  25. #define sf(n) scanf("%d", &n)
  26. #define sff(a, b) scanf("%d %d", &a, &b)
  27. #define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
  28. #define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
  29. #define pf printf
  30. #define FIN freopen("../date.txt","r",stdin)
  31. #define gcd(a, b) __gcd(a,b)
  32. #define lowbit(x) x&-x
  33. #define IO iOS::sync_with_stdio(false)
  34.  
  35. using namespace std;
  36. typedef long long LL;
  37. typedef unsigned long long ULL;
  38. const int maxn = 1e6 + ;
  39. const int maxm = 8e6 + ;
  40. const int INF = 0x3f3f3f3f;
  41. const int mod = 1e9 + ;
  42.  
  43. struct Aho_Corasick {
  44. int next[][], fail[], End[],vis[];
  45. int root, cnt;
  46. vector<int>ans;
  47. int newnode() {
  48. for (int i = ; i < ; i++) next[cnt][i] = -;
  49. End[cnt++] = ;
  50. return cnt - ;
  51. }
  52.  
  53. void init() {
  54. cnt = ;
  55. root = newnode();
  56. }
  57.  
  58. void insert(char buf[],int id) {
  59. int len = strlen(buf);
  60. int now = root;
  61. for (int i = ; i < len; i++) {
  62. if (next[now][buf[i]] == -) next[now][buf[i]] = newnode();
  63. now = next[now][buf[i]];
  64. }
  65. End[now]++;
  66. vis[now]=id;
  67. }
  68.  
  69. void build() {
  70. queue<int> Q;
  71. fail[root] = root;
  72. for (int i = ; i < ; i++)
  73. if (next[root][i] == -) next[root][i] = root;
  74. else {
  75. fail[next[root][i]] = root;
  76. Q.push(next[root][i]);
  77. }
  78. while (!Q.empty()) {
  79. int now = Q.front();
  80. Q.pop();
  81. for (int i = ; i < ; i++)
  82. if (next[now][i] == -) next[now][i] = next[fail[now]][i];
  83. else {
  84. fail[next[now][i]] = next[fail[now]][i];
  85. Q.push(next[now][i]);
  86. }
  87. }
  88. }
  89.  
  90. int query(char buf[]) {
  91. int len = strlen(buf);
  92. int now = root;
  93. int res = ;
  94. for (int i = ; i < len; i++) {
  95. now = next[now][buf[i]];
  96. int temp = now;
  97. while (temp != root) {
  98. res += End[temp];
  99. if (vis[temp]) ans.push_back(vis[temp]);
  100. // End[temp] = 0;
  101. temp = fail[temp];
  102. }
  103. }
  104. return res;
  105. }
  106. void pf_ans(){
  107. sort(ans.begin(),ans.end());
  108. for (int i= ;i<ans.size() ;i++) printf(" %d",ans[i]);
  109. printf("\n");
  110. ans.clear();
  111. }
  112. void debug() {
  113. for (int i = ; i < cnt; i++) {
  114. printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
  115. for (int j = ; j < ; j++) printf("%2d", next[i][j]);
  116. printf("]\n");
  117. }
  118. }
  119. }ac;
  120.  
  121. char buf[];
  122. int n,m;
  123. int main() {
  124. // FIN;
  125. while(~sf(n)){
  126. ac.init();
  127. for (int i = ; i <= n; ++i) {
  128. scanf("%s",buf);
  129. ac.insert(buf,i);
  130. }
  131. ac.build();
  132. sf(m);
  133. int tot=;
  134. for (int i = ; i <= m; ++i) {
  135. scanf("%s",buf);
  136. //fuck(i);
  137. if (ac.query(buf)) {
  138. tot++;
  139. printf("web %d:",i);
  140. ac.pf_ans();
  141. }
  142. }
  143. printf("total: %d\n",tot);
  144. }
  145. return ;
  146. }

病毒侵袭持续中 HDU - 3065

这题题意和上一题一样,多了一个输出出现次数。

  1. #include <set>
  2. #include <map>
  3. #include <stack>
  4. #include <queue>
  5. #include <cmath>
  6. #include <cstdio>
  7. #include <string>
  8. #include <vector>
  9. #include <time.h>
  10. #include <cstring>
  11. #include <iostream>
  12. #include <algorithm>
  13. #include <unordered_map>
  14.  
  15. #define pi acos(-1.0)
  16. #define eps 1e-9
  17. #define fi first
  18. #define se second
  19. #define rtl rt<<1
  20. #define rtr rt<<1|1
  21. #define bug printf("******\n")
  22. #define mem(a, b) memset(a,b,sizeof(a))
  23. #define name2str(x) #x
  24. #define fuck(x) cout<<#x" = "<<x<<endl
  25. #define sf(n) scanf("%d", &n)
  26. #define sff(a, b) scanf("%d %d", &a, &b)
  27. #define sfff(a, b, c) scanf("%d %d %d", &a, &b, &c)
  28. #define sffff(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
  29. #define pf printf
  30. #define FIN freopen("../date.txt","r",stdin)
  31. #define gcd(a, b) __gcd(a,b)
  32. #define lowbit(x) x&-x
  33. #define IO iOS::sync_with_stdio(false)
  34.  
  35. using namespace std;
  36. typedef long long LL;
  37. typedef unsigned long long ULL;
  38. const int maxn = 1e6 + ;
  39. const int maxm = 8e6 + ;
  40. const int INF = 0x3f3f3f3f;
  41. const int mod = 1e9 + ;
  42.  
  43. char str[][];
  44. char buf[];
  45. int n, m;
  46. struct Aho_Corasick {
  47. int next[*][], fail[*], End[*], num[];
  48. int root, cnt;
  49.  
  50. int newnode() {
  51. for (int i = ; i < ; i++) next[cnt][i] = -;
  52. End[cnt++] = ;
  53. return cnt - ;
  54. }
  55.  
  56. void init() {
  57. cnt = ;
  58. root = newnode();
  59. }
  60.  
  61. void insert(char buf[], int id) {
  62. int len = strlen(buf);
  63. int now = root;
  64. for (int i = ; i < len; i++) {
  65. if (next[now][buf[i]] == -) next[now][buf[i]] = newnode();
  66. now = next[now][buf[i]];
  67. }
  68. End[now] = id;
  69. }
  70.  
  71. void build() {
  72. queue<int> Q;
  73. fail[root] = root;
  74. for (int i = ; i < ; i++)
  75. if (next[root][i] == -) next[root][i] = root;
  76. else {
  77. fail[next[root][i]] = root;
  78. Q.push(next[root][i]);
  79. }
  80. while (!Q.empty()) {
  81. int now = Q.front();
  82. Q.pop();
  83. for (int i = ; i < ; i++)
  84. if (next[now][i] == -) next[now][i] = next[fail[now]][i];
  85. else {
  86. fail[next[now][i]] = next[fail[now]][i];
  87. Q.push(next[now][i]);
  88. }
  89. }
  90. }
  91.  
  92. void query(char buf[]) {
  93. for(int i = ;i <= n;i++) num[i] = ;
  94. int len = strlen(buf);
  95. int now = root;
  96. for (int i = ; i < len; i++) {
  97. now = next[now][buf[i]];
  98. int temp = now;
  99. while (temp != root) {
  100. if (End[temp]) num[End[temp]]++;
  101. // End[temp] = 0;
  102. temp = fail[temp];
  103. }
  104. }
  105. for (int i= ;i<=n ;i++)
  106. if (num[i]) printf("%s: %d\n",str[i],num[i]);
  107. }
  108.  
  109. void debug() {
  110. for (int i = ; i < cnt; i++) {
  111. printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
  112. for (int j = ; j < ; j++) printf("%2d", next[i][j]);
  113. printf("]\n");
  114. }
  115. }
  116. } ac;
  117.  
  118. int main() {
  119. //FIN;
  120. while (~sf(n)) {
  121. ac.init();
  122. for (int i = ; i <= n; ++i) {
  123. scanf("%s", str[i]);
  124. ac.insert(str[i], i);
  125. }
  126. ac.build();
  127. scanf("%s", buf);
  128. ac.query(buf);
  129. }
  130. return ;
  131. }

Detect the Virus ZOJ - 3430

这题本质上还是和上面一个套路只是恶心了很多。

题目是给先你n组经过编码后的病毒串:

编码就是将原串转成二进制后取每6位进行转化成10进制后与上面表格对应的字符串,

末尾不足6位补0,且原串个数为3k+1则在编码后的串里增加'==',

若个数为3k+2则增加'=',给定的模式串也是编码后的串,

所以需要进行反编码然后就是赤裸裸的AC自动机模版了。

注意转化后的字符范围为256(包括转义字符),strlen也无法使用,需要用unsigned char

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <queue>
  4.  
  5. #define sf(n) scanf("%d", &n)
  6. #define sff(a, b) scanf("%d %d", &a, &b)
  7.  
  8. using namespace std;
  9. typedef long long LL;
  10. typedef unsigned long long ULL;
  11. const int maxn = 1e6 + ;
  12. const int maxm = 8e6 + ;
  13. const int INF = 0x3f3f3f3f;
  14. const int mod = 1e9 + ;
  15.  
  16. unsigned char buf[];
  17. char str[];
  18. unsigned char s[];
  19. int n, m, tot;
  20.  
  21. struct Aho_Corasick {
  22. int next[ * ][], fail[ * ], End[ * ], vis[];
  23. int root, cnt;
  24.  
  25. int newnode() {
  26. for (int i = ; i < ; i++) next[cnt][i] = -;
  27. End[cnt++] = ;
  28. return cnt - ;
  29. }
  30.  
  31. void init() {
  32. cnt = ;
  33. root = newnode();
  34. }
  35.  
  36. void insert(unsigned char buf[], int len, int id) {
  37. int now = root;
  38. for (int i = ; i < len; i++) {
  39. if (next[now][buf[i]] == -) next[now][buf[i]] = newnode();
  40. now = next[now][buf[i]];
  41. }
  42. End[now] = id;
  43. }
  44.  
  45. void build() {
  46. queue<int> Q;
  47. fail[root] = root;
  48. for (int i = ; i < ; i++)
  49. if (next[root][i] == -) next[root][i] = root;
  50. else {
  51. fail[next[root][i]] = root;
  52. Q.push(next[root][i]);
  53. }
  54. while (!Q.empty()) {
  55. int now = Q.front();
  56. Q.pop();
  57. for (int i = ; i < ; i++)
  58. if (next[now][i] == -) next[now][i] = next[fail[now]][i];
  59. else {
  60. fail[next[now][i]] = next[fail[now]][i];
  61. Q.push(next[now][i]);
  62. }
  63. }
  64. }
  65.  
  66. int query(unsigned char buf[], int len, int n) {
  67. memset(vis, false, sizeof(vis));
  68. int now = root;
  69. for (int i = ; i < len; i++) {
  70. now = next[now][buf[i]];
  71. int temp = now;
  72. while (temp != root) {
  73. if (End[temp] != -)
  74. vis[End[temp]] = true;
  75. temp = fail[temp];
  76. }
  77. }
  78. int res = ;
  79. for (int i = ; i <= n; i++) if (vis[i]) res++;
  80. return res;
  81. }
  82.  
  83. void debug() {
  84. for (int i = ; i < cnt; i++) {
  85. printf("id = %3d,fail = %3d,end = %3d,chi = [", i, fail[i], End[i]);
  86. for (int j = ; j < ; j++) printf("%2d", next[i][j]);
  87. printf("]\n");
  88. }
  89. }
  90. } ac;
  91.  
  92. unsigned char Get(char ch) {
  93. if (ch >= 'A' && ch <= 'Z')return ch - 'A';
  94. if (ch >= 'a' && ch <= 'z')return ch - 'a' + ;
  95. if (ch >= '' && ch <= '')return ch - '' + ;
  96. if (ch == '+')return ;
  97. else return ;
  98. }
  99.  
  100. void change(unsigned char str[], int len) {
  101. int t = ;
  102. for (int i = ; i < len; i += ) {
  103. buf[t++] = ((str[i] << ) | (str[i + ] >> ));
  104. if (i + < len)
  105. buf[t++] = ((str[i + ] << ) | (str[i + ] >> ));
  106. if (i + < len)
  107. buf[t++] = ((str[i + ] << ) | str[i + ]);
  108. }
  109. tot = t;
  110. }
  111.  
  112. int main() {
  113. while (~sf(n)) {
  114. ac.init();
  115. for (int i = ; i <= n; ++i) {
  116. scanf("%s", str);
  117. int len = strlen(str);
  118. while (str[len - ] == '=')len--;
  119. for (int j = ; j < len; j++) s[j] = Get(str[j]);
  120. change(s, len);
  121. ac.insert(buf, tot, i);
  122. }
  123. ac.build();
  124. sf(m);
  125. for (int i = ; i <= m; i++) {
  126. scanf("%s", str);
  127. int len = strlen(str);
  128. while (str[len - ] == '=') len--;
  129. for (int j = ; j < len; j++) s[j] = Get(str[j]);
  130. change(s, len);
  131. printf("%d\n", ac.query(buf, tot, n));
  132. }
  133. printf("\n");
  134. }
  135. return ;
  136. }

HDU - 2222,HDU - 2896,HDU - 3065,ZOJ - 3430 AC自动机求文本串和模式串信息(模板题)的更多相关文章

  1. Detect the Virus ZOJ - 3430 AC自动机

    One day, Nobita found that his computer is extremely slow. After several hours' work, he finally fou ...

  2. ZOJ - 3430 ac自动机

    这题主要就是解码过程很恶心,不能用char存,一共wa了20发 题意:先给n串加密后的字符,然后m串加密后的字符,解码之后求n对应每个m的匹配数,很显然的ac自动机 加密过程是先用对应ascii表的标 ...

  3. hdu 3695:Computer Virus on Planet Pandora(AC自动机,入门题)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

  4. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. HDU 2846 (AC自动机+多文本匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2846 题目大意:有多个文本,多个模式串.问每个模式串中,有多少个文本?(匹配可重复) 解题思路: 传统 ...

  6. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意: 给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数. 思路: 如果做过poj2778 ...

  7. HDU 6138 Fleet of the Eternal Throne(AC自动机)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6138 [题目大意] 给出一些串,询问第x个串和第y个串的公共子串, 同时要求该公共子串为某个串的前 ...

  8. HDU 2896:病毒侵袭(AC自动机)

    http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:中文题意. 思路:AC自动机模板题.主要在于字符有128种,输出还要排序和去重! 注意是“total ...

  9. HDU 3695 Computer Virus on Planet Pandora(AC自动机模版题)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

随机推荐

  1. Jmeter-【JSON Extractor】-响应结果中三级key取值

    一.请求返回样式 二.取第三个option 三.查看结果

  2. delphi根据不同图片生成不规则窗口的实现(仅限于BMP格式)

    unit CreateImageForm; interface uses Windows, SysUtils, Variants, Classes, Graphics; procedure Creat ...

  3. NX二次开发-UFUN求两个对象最短距离UF_MODL_ask_minimum_dist

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_ui.h> UF_initialize() ...

  4. NX二次开发-UFUN结合NXOPEN开发_常用代码模板

    hpp //头文件 #include <NXOpen/Part.hxx> #include <NXOpen/PartCollection.hxx> #include <N ...

  5. flutter 插件

    flutter_spinkit loading动画

  6. iOS开发之UIMenuController

    1.简介 用于剪切.复制.粘贴.选择.选择ALL和DELETE命令的菜单界面. UITextField.UIWebView.UITextView自带有这种UIMenuController效果: 2.相 ...

  7. Debian怎么配置网卡(IP)

    来自:http://jingyan.baidu.com/article/a3f121e4d27a53fc9152bb65.html Debian可以配置静态IP.动态IP使Debian连上互联网.用户 ...

  8. 2019 USP Try-outs 练习赛

    // 好久没更博客了,最近打了很多场练习赛&校内PK赛,大概自闭忙于补题吧 // 9.26 周四练习赛 A. Kolkhozy 题意 有 n 个数 \(f[i]\) ,有 q 次询问(l, r ...

  9. Redis连不上的一些细节配置

    远程链接redis连不上,在确保防火墙设置正确的情况下 把redis.conf中的 bind 127.0.0.1注释 另外把protected-mode yes 改为protected-mode no

  10. 解决WIN8输入法的问题,Ctrl+空格,Ctrl+Shift,切换问题

    在WIN8中,我们曾经熟悉的的Ctrl+空格和Ctrl+Shift消失了,取而导致的是WIN+空格. 在这里先简单解释一下WIN8的输入法结构: 在WIN7以前的输入法中,输入法采用了平行目录的结构, ...