题目大意:给定很多个字串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\n", 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] != ‘\0‘; 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] != ‘\0‘; 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 }
时间: 2024-10-19 21:26:47