18.10.29 多模式串字符串匹配模板题~AC自动机
描述
给若干个模式串,以及若干个句子,判断每个句子里是否包含模式串。 句子和模式串都由小写字母组成
输入第一行是整数n,表示有n个模式串 ( n <= 1000)
接下来n行每行一个模式串。每个模式串长度不超过20
接下来一行是整数m,表示有m个句子 (m <= 1000)
接下来m行,每行一个句子,每个句子长度不超过1000输出对每个句子,如果包含某个模式串,则输出 YES, 否则输出 NO
样例输入
3
abc
def
gh
2
abcd
ak
样例输出
YES
NO
来源
Xu Yewen
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <algorithm> 4 #include <stack> 5 #include <string> 6 #include <math.h> 7 #include <queue> 8 #include <stdio.h> 9 #include <string.h> 10 #include <vector> 11 #include <fstream> 12 #include <set> 13 14 using namespace std; 15 const int maxn = 1005; 16 char line[maxn]; 17 int m, n,nodecou; 18 struct node { 19 node*next[26]; 20 node*prev; 21 bool isdanger; 22 node() { 23 memset(next, 0, sizeof(next)); 24 prev = NULL; 25 isdanger = false; 26 } 27 }tree[maxn*20]; 28 29 void build() { 30 for (int i = 0; i < 26; i++) 31 tree[0].next[i] = tree + 1; 32 tree[1].prev = tree; 33 queue<node*>q; 34 q.push(tree+1); 35 while (!q.empty()) { 36 node*now = q.front(); 37 q.pop(); 38 for (int i = 0; i < 26; i++) { 39 node*child = now->next[i]; 40 if (child) { 41 node*prev = now->prev; 42 while (prev->next[i] == NULL) 43 prev = prev->prev; 44 child->prev = prev->next[i]; 45 if (prev->isdanger) 46 child->isdanger = true; 47 q.push(child); 48 } 49 } 50 } 51 } 52 53 void search(char*str) { 54 node*first = tree + 1; 55 for (int i = 0; str[i] != '\0'; i++) { 56 while (first->next[str[i]-'a'] == NULL) 57 first = first->prev; 58 if (first->next[str[i]-'a']->isdanger) { 59 printf("YES\n"); 60 return; 61 } 62 first = first->next[str[i] - 'a']; 63 } 64 printf("NO\n"); 65 } 66 67 void init() { 68 scanf("%d", &n); 69 nodecou = 1; 70 for (int i = 1; i <= n; i++) { 71 scanf("%s",line); 72 node *first = tree + 1; 73 int l = strlen(line); 74 for (int i = 0; i!=l ; i++) { 75 if (first->next[line[i] - 'a'] == NULL) { 76 nodecou++; 77 first->next[line[i] - 'a'] = tree + nodecou; 78 } 79 first = first->next[line[i] - 'a']; 80 if (i == l - 1) 81 first->isdanger = true; 82 } 83 } 84 build(); 85 scanf("%d", &m); 86 while (m--) { 87 scanf("%s", line); 88 search(line); 89 } 90 } 91 92 int main() 93 { 94 init(); 95 return 0; 96 }
预热题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <string.h> 3 #include <algorithm> 4 #include <stack> 5 #include <string> 6 #include <math.h> 7 #include <queue> 8 #include <stdio.h> 9 #include <string.h> 10 #include <set> 11 #include <vector> 12 #define maxn 120005 13 #define inf 999999 14 #define EPS 1e-10 15 #define lowbit(x) (int)(x&(-x)) 16 using namespace std; 17 18 int n, m; 19 int nodecnt = 1; 20 struct node { 21 int next[26]; 22 int prev; 23 bool badnode; 24 bool endpoint; 25 node() { 26 memset(next, -1, sizeof(next)); 27 prev = -1; 28 badnode = endpoint = false; 29 } 30 }tree[maxn]; 31 char mode[1005]; 32 33 void insert() { 34 int p = 1; 35 for (int i = 0; mode[i]; i++) { 36 if (tree[p].next[mode[i] - 'a'] == -1) 37 tree[p].next[mode[i] - 'a'] = ++nodecnt; 38 p = tree[p].next[mode[i] - 'a']; 39 } 40 tree[p].badnode = true; 41 tree[p].endpoint = true; 42 } 43 44 void builddfa() { 45 deque<int>q; 46 q.push_back(1); 47 while (!q.empty()) { 48 int now = q.front(); q.pop_front(); 49 for (int i = 0; i < 26; i++) { 50 if (tree[now].next[i] != -1) { 51 int prev = tree[now].prev; 52 int next = tree[now].next[i]; 53 while (tree[prev].next[i] == -1) 54 prev = tree[prev].prev; 55 tree[next].prev = tree[prev].next[i]; 56 if (tree[prev].badnode) 57 tree[next].badnode = true; 58 q.push_back(next); 59 } 60 } 61 } 62 } 63 64 void query() { 65 int p = 1; 66 for (int i = 0; mode[i]; i++) { 67 while (tree[p].next[mode[i] - 'a'] == -1) 68 p = tree[p].prev; 69 p = tree[p].next[mode[i] - 'a']; 70 if (tree[p].badnode) { 71 printf("YES\n"); 72 return; 73 } 74 } 75 printf("NO\n"); 76 } 77 78 void init() { 79 scanf("%d", &n); 80 for (int i = 0; i < 26; i++) 81 tree[0].next[i] = 1; 82 tree[1].prev = 0; 83 for (int i = 1; i <= n; i++) { 84 scanf("%s", mode); 85 insert(); 86 } 87 builddfa(); 88 scanf("%d", &m); 89 while (m--) { 90 scanf("%s", mode); 91 query(); 92 } 93 } 94 95 int main() { 96 init(); 97 return 0; 98 }
补上数组做法↑
注定失败的战争,也要拼尽全力去打赢它;
就算输,也要输得足够漂亮。