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 {
 11     node *fail, *next[MAX];
 12     int count;
 13 }Mem_Pool[500001], *Trie_Queue[500001];
 14 static int Used_Node;
 15 static char pattern[10001], target[1000001];
 16 
 17 struct node *Get_New_Node(void);
 18 void Insert(struct node*);
 19 void Build_AC_Automation(struct node* const);
 20 static int Query(struct node* const);
 21 
 22 int main(void)
 23 {
 24     int case_sum, pattern_sum;
 25     scanf("%d", &case_sum);
 26     
 27     while (case_sum--)
 28     {
 29         Used_Node = 0;
 30         node *root = Get_New_Node();//每一次都拿一个新的根
 31         scanf("%d", &pattern_sum);
 32         getchar();
 33         while (pattern_sum--)
 34             Insert(root);
 35         Build_AC_Automation(root);
 36         gets(target);
 37         printf("%d
", Query(root));
 38     }
 39 }
 40 
 41 struct node *Get_New_Node(void)
 42 {
 43     Mem_Pool[Used_Node].count = 0;
 44     Mem_Pool[Used_Node].fail = NULL;
 45     memset(Mem_Pool[Used_Node].next, 0, sizeof(struct node *)*MAX);
 46 
 47     return &Mem_Pool[Used_Node++];
 48 }
 49 
 50 void Insert(struct node *root)
 51 {
 52     gets(pattern);
 53 
 54     node *p = root;
 55     int index;
 56     for (int i = 0; pattern[i] != ''; i++)
 57     {
 58         index = pattern[i] - 'a';
 59         if (p->next[index] == NULL)
 60             p->next[index] = Get_New_Node();
 61         p = p->next[index];
 62     }
 63     p->count++;//表示这个位置包含着一个字符,如果有多个则叠加就可以了。
 64 }
 65 
 66 void Build_AC_Automation(struct node *const root)//自动机的构造例程,其实就是个BFS
 67 {
 68     root->fail = NULL;
 69     int head = 0, back = 0;
 70     node *out = NULL, *tmp = NULL;
 71     Trie_Queue[back++] = root;
 72 
 73     while (head != back)
 74     {
 75         out = Trie_Queue[head++];
 76         for (int i = 0; i < MAX; i++)//枚举所有情况
 77             if (out->next[i] != NULL)
 78             {
 79                 if (out == root)
 80                     out->next[i]->fail = root;//如果out自己就是根,那么直接将其子节点的失败指针指向自己就好了
 81                 else
 82                 {
 83                     for (tmp = out->fail; tmp != NULL; tmp = tmp->fail)
 84                         if (tmp->next[i] != NULL)
 85                         {
 86                             out->next[i]->fail = tmp->next[i];
 87                             //如果还找到在其他地方找到和他一样的元素,那么我们就把失败指针指向这个元素
 88                             break;
 89                         }
 90                     if (tmp == NULL)
 91                         out->next[i]->fail = root;
 92                 }
 93                 Trie_Queue[back++] = out->next[i];
 94             }
 95     }
 96 }
 97 
 98 static int Query(struct node *const root)
 99 {
100     int ans = 0;
101     node *tmp = root, *other = NULL;
102     //tmp是跟着目标串的移动而移动的,other指针则表示在tire树的其他位置看还能不能匹配到其他字串
103     for (int i = 0; target[i] != ''; i++)
104     {
105         int index = target[i] - 'a';
106         while (tmp->next[index] == NULL && tmp != root)
107             tmp = tmp->fail;//沿着失败指针一直走
108         tmp = tmp->next[index];
109         tmp = (tmp == NULL) ? root : tmp;//检查如果是已经是root了,直接跳出来就好了
110         for (other = tmp; other != root && other->count != -1; other = other->fail)
111         {
112             ans += other->count;
113             other->count = -1;//标记一下,不要重复扫描
114         }
115     }
116     return ans;
117 }

  

原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5185793.html