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

 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 }
View Code

预热题

 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 }
View Code

 

补上数组做法↑

 

posted @ 2018-10-29 23:15  TobicYAL  阅读(702)  评论(0编辑  收藏  举报