模板

  1. #include<queue>
  2. #include<stdio.h>
  3. #include<string.h>
  4. using namespace std;
  5.  
  6. ;
  7. ;
  8. ;
  9.  
  10. struct Aho{
  11. struct StateTable{
  12. int Next[Letter];
  13. int fail, cnt;
  14. }Node[Max_Tot];
  15. int Size;
  16. queue<int> que;
  17.  
  18. inline void init(){
  19. while(!que.empty()) que.pop();
  20. memset(Node[].Next, , ].Next));
  21. Node[].fail = Node[].cnt = ;
  22. Size = ;
  23. }
  24.  
  25. inline void insert(char *s){
  26. int len = strlen(s);
  27. ;
  28. ; i<len; i++){
  29. int idx = s[i] - 'a';
  30. if(!Node[now].Next[idx]){
  31. memset(Node[Size].Next, , sizeof(Node[Size].Next));
  32. Node[Size].fail = Node[Size].cnt = ;
  33. Node[now].Next[idx] = Size++;
  34. }
  35. now = Node[now].Next[idx];
  36. }
  37. Node[now].cnt++;
  38. }
  39.  
  40. inline void BuildFail(){
  41. Node[].fail = -;
  42. que.push();
  43. while(!que.empty()){
  44. int top = que.front(); que.pop();
  45. ; i<Letter; i++){
  46. if(Node[top].Next[i]){
  47. ) Node[ Node[top].Next[i] ].fail = ;
  48. else{
  49. int v = Node[top].fail;
  50. ){
  51. if(Node[v].Next[i]){
  52. Node[ Node[top].Next[i] ].fail = Node[v].Next[i];
  53. break;
  54. }v = Node[v].fail;
  55. }) Node[ Node[top].Next[i] ].fail = ;
  56. }que.push(Node[top].Next[i]);
  57. }
  58. }
  59. }
  60. }
  61.  
  62. inline void Get(int u, int &res){
  63. while(u){
  64. res += Node[u].cnt;
  65. Node[u].cnt = ;
  66. u = Node[u].fail;
  67. }
  68. }
  69.  
  70. int Match(char *s){
  71. int len = strlen(s);
  72. , now = ;
  73. ; i<len; i++){
  74. int idx = s[i] - 'a';
  75. if(Node[now].Next[idx]) now = Node[now].Next[idx];
  76. else{
  77. int p = Node[now].fail;
  78. && Node[p].Next[idx]==) p = Node[p].fail;
  79. ) now = ;
  80. else now = Node[p].Next[idx];
  81. }
  82. if(Node[now].cnt) Get(now, res);
  83. }
  84. return res;
  85. }
  86. }ac;
  87.  
  88. char S[Max_Len];
  89. int main(void)
  90. {
  91. // ac.init();
  92. // ac.BuildFail();
  93. // ac.Match();
  94. // .....
  95. ;
  96. }
  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define MAX_N 1000006 /// 主串长度
  5. #define MAX_Tot 500005 /// 字典树上可能的最多的结点数 = Max串数 * Max串长
  6.  
  7. struct Aho{
  8. struct state{
  9. ];
  10. int fail,cnt;
  11. }st[MAX_Tot]; /// 节点结构体
  12. int Size; /// 节点个数
  13. queue<int> que;/// BFS构建fail指针的队列
  14.  
  15. void init(){
  16. while(que.size())que.pop();/// 清空队列
  17. ;i<MAX_Tot;i++){/// 初始化节点,有时候 MLE 的时候,可以尝试将此初始化放到要操作的时候再来初始化
  18. memset(st[i].next,,sizeof(st[i].next));
  19. st[i].fail=st[i].cnt=;
  20. }
  21. Size=;/// 本来就有一个空的根节点
  22. }
  23.  
  24. void insert(char *S){/// 插入模式串
  25. int len=strlen(S);/// 复杂度为O(n),所以别写进for循环
  26. ;/// 当前结点是哪一个,从0即根开始
  27. ;i<len;i++){
  28. char c = S[i];
  29. if(!st[now].next[c-'a']) st[now].next[c-'a']=Size++;
  30. now=st[now].next[c-'a'];
  31. }
  32. st[now].cnt++;/// 给这个串末尾打上标记
  33. }
  34.  
  35. void build(){/// 构建 fail 指针
  36. st[].fail=-;/// 根节点的 fail 指向自己
  37. que.push();/// 将根节点入队
  38.  
  39. while(que.size()){
  40. int top = que.front(); que.pop();
  41.  
  42. ; i<; i++){
  43. if(st[top].next[i]){/// 如果当前节点有 i 这个儿子
  44. ) st[st[top].next[i]].fail=;/// 第二层节点 fail 应全指向根
  45. else {
  46. int v = st[top].fail;/// 走向 top 节点父亲的 fail 指针指向的地方,尝试找一个最长前缀
  47. ){/// 如果走到 -1 则说明回到根了
  48. if(st[v].next[i]){/// 如果有一个最长前缀后面接着的也是 i 这个字符,则说明 top->next[i] 的 fail 指针可以指向这里
  49. st[st[top].next[i]].fail = st[v].next[i];
  50. break;/// break 保证找到的前缀是最长的
  51. }
  52. v = st[v].fail;/// 否则继续往父亲的父亲的 fail 跳,即后缀在变短( KMP 思想 )
  53. } ) st[st[top].next[i]].fail=;/// 如果从头到尾都没找到,那么就只能指向根了
  54. } que.push(st[top].next[i]);/// 将这个节点入队,为了下面建立 fail 节点做准备
  55. }
  56. }
  57. }
  58. }
  59.  
  60. int get(int u){
  61. ;
  62. while(u){
  63. res = res + st[u].cnt;
  64. st[u].cnt = ;
  65. u = st[u].fail;
  66. }
  67. return res;
  68. }
  69.  
  70. int match(char *S){
  71. int len = strlen(S);/// 主串长度
  72. ,now=;/// 主串能够和多少个模式串匹配的结果、当前的节点是哪一个
  73. ; i<len; i++){
  74. char c = S[i];
  75. if(st[now].next[c-'a']) now=st[now].next[c-'a'];/// 如果匹配了,则不用跳到 fail 处,直接往下一个字符匹配
  76. else {
  77. int p = st[now].fail;
  78. && st[p].next[c- ) p=st[p].fail;/// 跳到 fail 指针处去匹配 c-'a' ,直到跳到 -1 也就是没得跳的时候
  79. ) now = ;/// 如果全部都不匹配,只能回到根节点了
  80. else now = st[p].next[c-'a'];/// 否则当前节点就是到达了能够匹配的 fail 指针指向处
  81. }
  82. if(st[now].cnt)/// 如果当前节点是个字符串的结尾,这个时候就能统计其对于答案贡献了,答案的贡献应该是它自己 + 它所有 fail 指针指向的节点
  83. /// 实际也就是它匹配了,那么它的 fail 指向的前缀以及 fail 的 fail 实际上也应该是匹配了,所以循环跳 fail 直到无法再跳为止
  84. res = res + get(now);
  85. }
  86. return res;
  87. }
  88. }ac;
  89.  
  90. int T;
  91. int N;
  92. char S[MAX_N];
  93. int main(){
  94. // ac.init();
  95. // ac.build();
  96. // ac.match();
  97. // ...
  98. ;
  99. }

带注释

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. struct Node
  5. {
  6. int cnt;//是否为该单词的最后一个结点
  7. Node *fail;//失败指针
  8. Node *next[];//Trie中每个结点的各个节点
  9. }*queue[];//队列,方便用BFS构造失败指针
  10. ];//主字符串
  11. ];//需要查找的单词
  12. Node *root;//头结点
  13. void Init(Node *root)//每个结点的初始化
  14. {
  15. root->cnt=;
  16. root->fail=NULL;
  17. ;i<;i++)
  18. root->next[i]=NULL;
  19. }
  20. void Build_trie(char *keyword)//构建Trie树
  21. {
  22. Node *p,*q;
  23. int i,v;
  24. int len=strlen(keyword);
  25. ,p=root;i<len;i++)
  26. {
  27. v=keyword[i]-'a';
  28. if(p->next[v]==NULL)
  29. {
  30. q=(struct Node *)malloc(sizeof(Node));
  31. Init(q);
  32. p->next[v]=q;//结点链接
  33. }
  34. p=p->next[v];//指针移动到下一个结点
  35. }
  36. p->cnt++;//单词最后一个结点cnt++,代表一个单词
  37. }
  38. void Build_AC_automation(Node *root)
  39. {
  40. ,tail=;//队列头、尾指针
  41. queue[head++]=root;//先将root入队
  42. while(head!=tail)
  43. {
  44. Node *p=NULL;
  45. Node *temp=queue[tail++];//弹出队头结点
  46. ;i<;i++)
  47. {
  48. if(temp->next[i]!=NULL)//找到实际存在的字符结点
  49. { //temp->next[i] 为该结点,temp为其父结点
  50. if(temp==root)//若是第一层中的字符结点,则把该结点的失败指针指向root
  51. temp->next[i]->fail=root;
  52. else
  53. {
  54. //依次回溯该节点的父节点的失败指针直到某节点的next[i]与该节点相同,
  55. //则把该节点的失败指针指向该next[i]节点;
  56. //若回溯到 root 都没有找到,则该节点的失败指针指向 root
  57. p=temp->fail;//将该结点的父结点的失败指针给p
  58. while(p!=NULL)
  59. {
  60. if(p->next[i]!=NULL)
  61. {
  62. temp->next[i]->fail=p->next[i];
  63. break;
  64. }
  65. p=p->fail;
  66. }
  67. //让该结点的失败指针也指向root
  68. if(p==NULL)
  69. temp->next[i]->fail=root;
  70. }
  71. queue[head++]=temp->next[i];//每处理一个结点,都让该结点的所有孩子依次入队
  72. }
  73. }
  74. }
  75. }
  76. int query(Node *root)
  77. { //i为主串指针,p为模式串指针
  78. ;
  79. Node *p=root;
  80. int len=strlen(s);
  81. ;i<len;i++)
  82. {
  83. v=s[i]-'a';
  84. //由失败指针回溯查找,判断s[i]是否存在于Trie树中
  85. while(p->next[v]==NULL && p!=root)
  86. p=p->fail;
  87. p=p->next[v];//找到后p指针指向该结点
  88. if(p==NULL)//若指针返回为空,则没有找到与之匹配的字符
  89. p=root;
  90. Node *temp=p;//匹配该结点后,沿其失败指针回溯,判断其它结点是否匹配
  91. while(temp!=root)//匹配结束控制
  92. {
  93. )//判断该结点是否被访问
  94. {
  95. count+=temp->cnt;//由于cnt初始化为 0,所以只有cnt>0时才统计了单词的个数
  96. temp->cnt=-;//标记已访问过
  97. }
  98. else//结点已访问,退出循环
  99. break;
  100. temp=temp->fail;//回溯 失败指针 继续寻找下一个满足条件的结点
  101. }
  102. }
  103. return count;
  104. }
  105. int main()
  106. {
  107. int T,n;
  108. scanf("%d",&T);
  109. while(T--)
  110. {
  111. root=(struct Node *)malloc(sizeof(Node));
  112. Init(root);
  113. scanf("%d",&n);
  114. ;i<n;i++)
  115. {
  116. scanf("\n%s",keyword);
  117. Build_trie(keyword);
  118. }
  119. Build_AC_automation(root);
  120. scanf("\n%s",s);
  121. printf("%d\n",query(root));
  122. }
  123. ;
  124. }

指针版

  1. ;
  2. ;
  3. ;
  4.  
  5. struct Aho{
  6. struct StateTable{
  7. int nxt[Letter];
  8. int fail, cnt;
  9. bool vis;
  10. void init(){
  11. memset(nxt, , sizeof(nxt));
  12. fail = ;
  13. cnt = ;
  14. vis = false;
  15. }
  16. }Node[max_node];
  17.  
  18. int sz;
  19. queue<int> que;
  20.  
  21. inline ].init(); sz = ; }
  22.  
  23. inline void insert(char *s, int len){
  24. ;
  25. ; i<len; i++){
  26. int idx = s[i] - 'a';
  27. if(!Node[now].nxt[idx]){
  28. Node[sz].init();
  29. Node[now].nxt[idx] = sz++;
  30. }
  31. now = Node[now].nxt[idx];
  32. }
  33. Node[now].cnt++;
  34. }
  35.  
  36. inline void build(){
  37. Node[].fail = -;
  38. que.push();
  39. while(!que.empty()){
  40. int top = que.front(); que.pop();
  41. ; i<Letter; i++){
  42. if(Node[top].nxt[i]){
  43. ) Node[ Node[top].nxt[i] ].fail = ;
  44. else{
  45. int v = Node[top].fail;
  46. ){
  47. if(Node[v].nxt[i]){
  48. Node[ Node[top].nxt[i] ].fail = Node[v].nxt[i];
  49. break;
  50. }v = Node[v].fail;
  51. }) Node[ Node[top].nxt[i] ].fail = ;
  52. }que.push(Node[top].nxt[i]);
  53. }?Node[ Node[top].fail ].nxt[i]:;
  54. }
  55. }
  56. }
  57.  
  58. int Match(char *s){
  59. , res = ;
  60. ; s[i]!='\0'; i++){
  61. int idx = s[i] - 'a';
  62. now = Node[now].nxt[idx];
  63. int tmp = now;
  64. && !Node[tmp].vis){
  65. res += Node[tmp].cnt;
  66. Node[tmp].vis = true;
  67. Node[tmp].cnt = ;
  68. tmp = Node[tmp].fail;
  69. }
  70. }
  71. return res;
  72. }
  73. }ac;

Trie 图

参考博客

http://blog.csdn.net/niushuai666/article/details/7002823
http://blog.csdn.net/silence401/article/details/52662605
http://blog.csdn.net/liu940204/article/details/51345954
http://blog.csdn.net/creatorx/article/details/71100840

相关题目

HDU 2222

题意 : 给出 n 个模式串再给出一个主串,问你有多少个模式串曾在这个主串上出现过

分析 : 模板题,注意每一次计数完成后要将 cnt 的值置为 0 以免重复计算

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. #define MAX_N 1000006 /// 主串长度
  5. #define MAX_Tot 500005 /// 字典树上可能的最多的结点数 = Max串数 * Max串长
  6.  
  7. struct Aho{
  8. struct state{
  9. ];
  10. int fail,cnt;
  11. }st[MAX_Tot]; /// 节点结构体
  12. int Size; /// 节点个数
  13. queue<int> que;/// BFS构建fail指针的队列
  14.  
  15. void init(){
  16. while(que.size())que.pop();/// 清空队列
  17. ;i<MAX_Tot;i++){/// 初始化节点,有时候 MLE 的时候,可以尝试将此初始化放到要操作的时候再来初始化
  18. memset(st[i].next,,sizeof(st[i].next));
  19. st[i].fail=st[i].cnt=;
  20. }
  21. Size=;/// 本来就有一个空的根节点
  22. }
  23.  
  24. void insert(char *S){/// 插入模式串
  25. int len=strlen(S);/// 复杂度为O(n),所以别写进for循环
  26. ;/// 当前结点是哪一个,从0即根开始
  27. ;i<len;i++){
  28. char c = S[i];
  29. if(!st[now].next[c-'a']) st[now].next[c-'a']=Size++;
  30. now=st[now].next[c-'a'];
  31. }
  32. st[now].cnt++;/// 给这个串末尾打上标记
  33. }
  34.  
  35. void build(){/// 构建 fail 指针
  36. st[].fail=-;/// 根节点的 fail 指向自己
  37. que.push();/// 将根节点入队
  38.  
  39. while(que.size()){
  40. int top = que.front(); que.pop();
  41.  
  42. ; i<; i++){
  43. if(st[top].next[i]){/// 如果当前节点有 i 这个儿子
  44. ) st[st[top].next[i]].fail=;/// 第二层节点 fail 应全指向根
  45. else {
  46. int v = st[top].fail;/// 走向 top 节点父亲的 fail 指针指向的地方,尝试找一个最长前缀
  47. ){/// 如果走到 -1 则说明回到根了
  48. if(st[v].next[i]){/// 如果有一个最长前缀后面接着的也是 i 这个字符,则说明 top->next[i] 的 fail 指针可以指向这里
  49. st[st[top].next[i]].fail = st[v].next[i];
  50. break;/// break 保证找到的前缀是最长的
  51. }
  52. v = st[v].fail;/// 否则继续往父亲的父亲的 fail 跳,即后缀在变短( KMP 思想 )
  53. } ) st[st[top].next[i]].fail=;/// 如果从头到尾都没找到,那么就只能指向根了
  54. } que.push(st[top].next[i]);/// 将这个节点入队,为了下面建立 fail 节点做准备
  55. }
  56. }
  57. }
  58. }
  59.  
  60. int get(int u){
  61. ;
  62. while(u){
  63. res = res + st[u].cnt;
  64. st[u].cnt = ;
  65. u = st[u].fail;
  66. }
  67. return res;
  68. }
  69.  
  70. int match(char *S){
  71. int len = strlen(S);/// 主串长度
  72. ,now=;/// 主串能够和多少个模式串匹配的结果、当前的节点是哪一个
  73. ; i<len; i++){
  74. char c = S[i];
  75. if(st[now].next[c-'a']) now=st[now].next[c-'a'];/// 如果匹配了,则不用跳到 fail 处,直接往下一个字符匹配
  76. else {
  77. int p = st[now].fail;
  78. && st[p].next[c- ) p=st[p].fail;/// 跳到 fail 指针处去匹配 c-'a' ,直到跳到 -1 也就是没得跳的时候
  79. ) now = ;/// 如果全部都不匹配,只能回到根节点了
  80. else now = st[p].next[c-'a'];/// 否则当前节点就是到达了能够匹配的 fail 指针指向处
  81. }
  82. if(st[now].cnt)/// 如果当前节点是个字符串的结尾,这个时候就能统计其对于答案贡献了,答案的贡献应该是它自己 + 它所有 fail 指针指向的节点
  83. /// 实际也就是它匹配了,那么它的 fail 指向的前缀以及 fail 的 fail 实际上也应该是匹配了,所以循环跳 fail 直到无法再跳为止
  84. res = res + get(now);
  85. }
  86. return res;
  87. }
  88. }aho;
  89.  
  90. int T;
  91. int N;
  92. char S[MAX_N];
  93. int main(){
  94. scanf("%d",&T);
  95. while(T--){
  96. aho.init();
  97. scanf("%d",&N);
  98. ;i<N;i++){
  99. scanf("%s",S);
  100. aho.insert(S);
  101. }
  102. aho.build();
  103. scanf("%s",S);
  104. printf("%d\n",aho.match(S));
  105. }
  106. ;
  107. }

HDU 2896

题意 : 中文就不赘述了……

分析 : 模板题,可见的ascii码范围的话,直接开到128即可

  1. #include<queue>
  2. #include<stdio.h>
  3. #include<string.h>
  4. using namespace std;
  5.  
  6. ;
  7. ;
  8. ;
  9.  
  10. struct Aho{
  11. struct StateTable{
  12. int Next[Letter];
  13. int fail, id;
  14. }Node[Max_Tot];
  15. int Size;
  16. queue<int> que;
  17.  
  18. inline void init(){
  19. while(!que.empty()) que.pop();
  20. memset(Node[].Next, , ].Next));
  21. Node[].fail = Node[].id = ;
  22. Size = ;
  23. }
  24.  
  25. inline void insert(char *s, const int id){
  26. int len = strlen(s);
  27. ;
  28. ; i<len; i++){
  29. int idx = s[i];
  30. if(!Node[now].Next[idx]){
  31. memset(Node[Size].Next, , sizeof(Node[Size].Next));
  32. Node[Size].fail = Node[Size].id = ;
  33. Node[now].Next[idx] = Size++;
  34. }
  35. now = Node[now].Next[idx];
  36. }
  37. Node[now].id = id;
  38. }
  39.  
  40. inline void BuildFail(){
  41. Node[].fail = -;
  42. que.push();
  43. while(!que.empty()){
  44. int top = que.front(); que.pop();
  45. ; i<Letter; i++){
  46. if(Node[top].Next[i]){
  47. ) Node[ Node[top].Next[i] ].fail = ;
  48. else{
  49. int v = Node[top].fail;
  50. ){
  51. if(Node[v].Next[i]){
  52. Node[ Node[top].Next[i] ].fail = Node[v].Next[i];
  53. break;
  54. }v = Node[v].fail;
  55. }) Node[ Node[top].Next[i] ].fail = ;
  56. }que.push(Node[top].Next[i]);
  57. }
  58. }
  59. }
  60. }
  61.  
  62. inline void Get(int u, bool *used){
  63. while(u){
  64. if(!used[Node[u].id] && Node[u].id)
  65. used[Node[u].id] = true;
  66. u = Node[u].fail;
  67. }
  68. }
  69.  
  70. bool Match(char *s, bool *used){
  71. ;
  72. bool ok = false;
  73. ; s[i]; i++){
  74. int idx = s[i];
  75. if(Node[now].Next[idx]) now = Node[now].Next[idx];
  76. else{
  77. int p = Node[now].fail;
  78. && Node[p].Next[idx]==){
  79. p = Node[p].fail;
  80. }
  81. ) now = ;
  82. else now = Node[p].Next[idx];
  83. }
  84. if(Node[now].id) { Get(now, used); ok = true; }
  85. }
  86. if(ok) return true;
  87. return false;
  88. }
  89. }ac;
  90.  
  91. char S[Max_Len];
  92. ];
  93. int main(void)
  94. {
  95. int n, m;
  96. memset(used, false, sizeof(used));
  97. while(~scanf("%d", &n)){
  98. ac.init();
  99. ; i<=n; i++){
  100. scanf("%s", S);
  101. ac.insert(S, i);
  102. }
  103. ac.BuildFail();
  104. ;
  105. scanf("%d", &m);
  106. ; i<=m; i++){
  107. scanf("%s", S);
  108. if(ac.Match(S, used)){
  109. printf("web %d:", i);
  110. ; j<=n; j++){
  111. if(used[j]){
  112. printf(" %d", j);
  113. used[j] = false;
  114. }
  115. }puts("");
  116. ans++;
  117. }
  118. }
  119. printf("total: %d\n", ans);
  120. }
  121. ;
  122. }

HDU 3065

题意 : 中文就不赘述了......

分析 : 还是模板题

  1. #include<queue>
  2. #include<stdio.h>
  3. #include<string.h>
  4. using namespace std;
  5.  
  6. ;
  7. ;
  8. ;
  9.  
  10. struct Aho{
  11. struct StateTable{
  12. int Next[Letter];
  13. int fail, id;
  14. }Node[Max_Tot];
  15. int Size;
  16. queue<int> que;
  17.  
  18. inline void init(){
  19. while(!que.empty()) que.pop();
  20. memset(Node[].Next, , ].Next));
  21. Node[].fail = Node[].id = ;
  22. Size = ;
  23. }
  24.  
  25. inline void insert(char *s, int id){
  26. int len = strlen(s);
  27. ;
  28. ; i<len; i++){
  29. int idx = s[i] - 'A';
  30. if(!Node[now].Next[idx]){
  31. memset(Node[Size].Next, , sizeof(Node[Size].Next));
  32. Node[Size].fail = Node[Size].id = ;
  33. Node[now].Next[idx] = Size++;
  34. }
  35. now = Node[now].Next[idx];
  36. }
  37. Node[now].id = id;
  38. }
  39.  
  40. inline void BuildFail(){
  41. Node[].fail = -;
  42. que.push();
  43. while(!que.empty()){
  44. int top = que.front(); que.pop();
  45. ; i<Letter; i++){
  46. if(Node[top].Next[i]){
  47. ) Node[ Node[top].Next[i] ].fail = ;
  48. else{
  49. int v = Node[top].fail;
  50. ){
  51. if(Node[v].Next[i]){
  52. Node[ Node[top].Next[i] ].fail = Node[v].Next[i];
  53. break;
  54. }v = Node[v].fail;
  55. }) Node[ Node[top].Next[i] ].fail = ;
  56. }que.push(Node[top].Next[i]);
  57. }
  58. }
  59. }
  60. }
  61.  
  62. inline void Get(int u, int *arr){
  63. while(u){
  64. if(Node[u].id) arr[Node[u].id]++;
  65. u = Node[u].fail;
  66. }
  67. }
  68.  
  69. inline void Match(char *s, int *arr){
  70. ;
  71. ; s[i]; i++){
  72. ; continue; }
  73. int idx = s[i] - 'A';
  74. if(Node[now].Next[idx]) now = Node[now].Next[idx];
  75. else{
  76. int p = Node[now].fail;
  77. && Node[p].Next[idx]==) p = Node[p].fail;
  78. ) now = ;
  79. else now = Node[p].Next[idx];
  80. }
  81. if(Node[now].id) Get(now, arr);
  82. }
  83. }
  84. }ac;
  85.  
  86. char S[Max_Len];
  87. ];
  88. ][];
  89. int main(void)
  90. {
  91. memset(arr, , sizeof(arr));
  92. int n;
  93. while(~scanf("%d", &n)){
  94.  
  95. ac.init();
  96. ; i<=n; i++){
  97. scanf("%s", str[i]);
  98. ac.insert(str[i], i);
  99. }
  100. ac.BuildFail();
  101. scanf("%s", S);
  102. ac.Match(S, arr);
  103. ; i<=n; i++){
  104. if(arr[i]){
  105. printf("%s: %d\n", str[i], arr[i]);
  106. arr[i] = ;
  107. }
  108. }
  109. }
  110. ;
  111. }

AC自动机及其模板的更多相关文章

  1. AC自动机 (模板)

    AC自动机是用来干什么的: AC自动机是用来解决多模匹配问题,例如有单词s1,s2,s3,s4,s5,s6,问:在文本串ss中有几个单词出现过,类似. AC自动机实现这个功能需要三个部分: 1.将所有 ...

  2. [hdu2222]ac自动机(模板)

    题意:一个文本串+多个模板串的匹配问题 思路:裸的ac自动机. #pragma comment(linker, "/STACK:10240000,10240000") #inclu ...

  3. HDOJ-3065(AC自动机+每个模板串的出现次数)

    病毒侵袭持续中 HDOJ-3065 第一个需要注意的是树节点的个数也就是tree的第一维需要的空间是多少:模板串的个数*最长模板串的长度 一开始我的答案总时WA,原因是我的方法一开始不是这样做的,我是 ...

  4. luogu AC自动机(模板)

    完全忘了AC自动机怎么写了qwq,更别说AC自动机上DP了. 今天就好好地学习字符串好了qwq 提一下AC自动机的时间复杂度--设n是模式串的个数,m是文本串的长度,l是模式串的平均长度,那么它的时间 ...

  5. ac自动机俩模板

    ac自动机算法正确性还没有理解,算法导论也看不懂..等懂了回来发算法专题. #include <cstdio> #include <cstring> using namespa ...

  6. AC自动机(模板) LUOGU P3808

    传送门 解题思路 AC自动机,是解决多模匹配问题的算法,是字典树与kmp结合的算法,可以解决许多子串在文本串中出现的次数等信息.关键是实现一个fail指针,是指向更靠上的前缀相同字母,从而可以实现在文 ...

  7. AC自动机(模板+例题)

    首先要明白AC自动机是干什么的: AC自动机其实就是一种多模匹配算法,那么你可能会问什么叫做多模匹配算法.下面是我对多模匹配的理解,与多模与之对于的是单模,单模就是给你一个单词,然后给你一个字符串,问 ...

  8. AC自动机(模板)

    #include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> ...

  9. hdu 2222 ac自动机更新模板 for onSite contest

    http://acm.split.hdu.edu.cn/showproblem.php?pid=2222 #include <cstdio> #include <cstdlib> ...

随机推荐

  1. 2017-0ctf-babyheap

    fastbin attack + unsortedbin attack + __malloc_hook 的基础利用 题目下载 : https://uaf.io/assets/0ctfbabyheap ...

  2. 【MM系列】SAP MM模块-关于批次特性的查看和获取

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM模块-关于批次特性的查看 ...

  3. 5.使用github脚本LAZY----几个最好的发行版----自定义终端----基本命令

    使用现成的脚本 LAZY * 如果您不想手动设置,可以用这个脚本帮您设置 访问:github.com/arismelachroinos/lscript sudo apt-get git git clo ...

  4. 【Linux开发】直接渲染管理

    原文地址:https://dri.freedesktop.org/wiki/DRM/ DRM - Direct Rendering Manager DRM是一个内核级的设备驱动,既可以编译到内核中也可 ...

  5. Nginx/Nginx配置文件

    nginx.conf配置文件 mac目录位置:/usr/local/etc/nginx/ ubuntu目录位置:/etc/nginx nginx.conf配置 /* 全局块:配置影响nginx全局的指 ...

  6. eclipse sts 常规操作

    项目:右键 refresh 右键 maven -> update project 重新remove add project    重启软件,电脑 1.项目冗余 Package Explorer ...

  7. java中Map的put函数和get函数用法

    ---内容开始--- 没有比较完整的说明他们的用法,一般就只能看源函数,但是看起来比较的费劲. 那么究竟put函数和get函数的用法是如何的呢? 当然java中的Map集合是有Key和Value的. ...

  8. c++多线程并发学习笔记(1)

    共享数据带来的问题:条件竞争 避免恶性条件竞争的方法: 1. 对数据结构采用某种保护机制,确保只有进行修改的线程才能看到修改时的中间状态.从其他访问线程的角度来看,修改不是已经完成了,就是还没开始. ...

  9. [FJOI2007]轮状病毒 题解(dp(找规律)+高精度)

    [FJOI2007]轮状病毒 题解(dp(找规律)+高精度) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1335733 没什么好说的,直接把规律找出来,有 ...

  10. phpstorm配置成sublime的代码高亮逼格风格

    使用sublime text3的风格来编程感觉是相当逼格的,然而在php的时候还是觉得phpstorm用起来更顺手一点. 正好在phpstorm中也有配置sublime类似风格的插件,这里来教大家如何 ...