【HNOI2004】L语言

Description

给定n个模式串和m个文本串,对于每个文本串,求出这个文本串在模式串中最大匹配长度。

Solution

我们采用AC自动机求解。

首先构建自动机,在Trie上保存模式串,之后通过bfs求出失配数组(AC自动机的模板操作),之后处理匹配操作。

这里的一个难点就是我们需要记录最大的匹配长度(而不是是否能匹配),因此我们开一个数组记录当前文本串能匹配的最大长度是多少,那么当AC自动机匹配完一个模式串时,如果文本串中这个模式串之前都匹配完成,那么我们在这里标记。跑一边AC自动机,最后倒序扫一遍标记数组,第一个扫描到标记的位置就是最大长度。

Code

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int n, m;
 5 char c[21][11], s[1050010];
 6 int ch[100010][27], val[100010], vis[1050010], dep[100010], f[100010], tot;
 7 void insert(char *a) {
 8     int now = 0;
 9     int l = strlen(a);
10     for (int i = 0; i < l; ++i) {
11         if (!ch[now][a[i] - 'a']) {
12             ch[now][a[i] - 'a'] = ++tot;
13             dep[tot] = dep[now] + 1;
14         }
15         now = ch[now][a[i] - 'a'];
16     }
17     val[now] = 1;
18     return ;
19 }
20 queue <int> q;
21 void bfs() {
22     for (int i = 0; i < 26; ++i) {
23         if (ch[0][i]) {
24             f[ch[0][i]] = 0;
25             q.push(ch[0][i]);
26         }
27     }
28     while (!q.empty()) {
29         int now = q.front();
30         q.pop();
31         for (int i = 0; i < 26; ++i) {
32             if (ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]);
33             else ch[now][i] = ch[f[now]][i];
34         }
35     }
36     return ;
37 }
38 int query(char *a) {
39     vis[0] = 1;
40     int now = 0, l = strlen(a);
41     for (int i = 0; i < l; ++i) {
42         now = ch[now][a[i] - 'a'];
43         for (int j = now; j; j = f[j]) 
44             if (val[j] && vis[i + 1 - dep[j]]) {
45                 vis[i + 1] = 1;
46                 break ;
47             }
48     }
49     for (int i = l; i; --i)
50         if (vis[i]) return i;
51     return 0;
52 }
53 int main() {
54     scanf("%d%d", &n, &m);
55     for (register int i = 1; i <= n; ++i) {
56         scanf("%s", c[i]);
57         insert(c[i]);
58     }
59     bfs();
60     for (register int i = 1; i <= m; ++i) {
61         memset(vis, 0, sizeof(vis));
62         scanf("%s", s);
63         printf("%d\n", query(s));
64     }
65     return 0;
66 }
AC Code

猜你喜欢

转载自www.cnblogs.com/shl-blog/p/11255415.html