天天看点

KMP,AC自动机

KMP

http://www.matrix67.com/blog/archives/115

注意这个从1开始字符串,从0开始不好写,不过不优化fail的从0还是好写- -!

1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 using namespace std;
 6 #define maxn 1000005
 7 int n, m, k;
 8 int a[maxn],fail[maxn];
 9 char str1[maxn], str2[maxn];
10 void init(){
11     int j = 0;
12     for (int i = 2; i <= m; i++){
13         while (j&&str2[i] != str2[j + 1])j = fail[j];
14         if (str2[i] == str2[j + 1])j++;
15         fail[i] = j;
16     }
17 }
18 void kmp(){
19     int j = 0; k = 0;
20     for (int i = 1; i <= n; i++){
21         while (j&&str1[i] != str2[j + 1])j = fail[j];
22         if (str1[i] == str2[j + 1])j++;
23         if (j == m){ a[k++] = i - m + 1; j = fail[j]; }
24     }
25 }
26 int main(){
27     while (~scanf("%s%s", str1+1, str2+1)){
28         n = strlen(str1 + 1);
29         m = strlen(str2 + 1);
30         init();
31         kmp();
32         for (int i = 0; i < k; i++)printf(i==k-1?"%d\n":"%d ", a[i]);
33     }
34     return 0;
35 }      

View Code

AC自动机

http://wenku.baidu.com/link?url=_WLP8BEXP8hSTvQPl_drqiSeOkkEkno0LveEwD5ZRSSb5zolHaV6kVXoELIdrxpWriPjL_O6od4FrMWvpB5dPcX28qbQ0BOd5nBCagt4IN_

首先要把深度为i之前的fail指针求出来才能求深度为i的fail指针,BFS刚好符合!

最后没看懂的再看看下面的这个回答

某某:我把我的想法说下`是不是`对 ``你最后的那个trie先在要求的是she中h的失败指针,而对``h深度`h-1的失败指针都已经求出来(可以通过归纳证明)所以

对h只要沿着它父亲走失败指针的看失败指针指向的节点是否有一个 儿子和h 相等,而由失败指针的定义。h以上有n个和失败指针到 root之间

匹配,所以 如果找到一个h 说明有n+1个匹配 得证。 希作者看到后联系我- - 看我的理解对不对``还是有更加具体化的思路我没有想到```

这种代码肯定会被各种卡的,知道写,乱改就可以了。。。我都懒得去知道以前写的了

1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 #include <algorithm>
 5 #include <iostream>
 6 using namespace std;
 7 #define maxn 1005005
 8 #define sz_ 26
 9 int n, k, t, sz, cnt;
10 int m[10005];
11 int q[maxn];
12 int ch[maxn][sz_];
13 int fail[maxn];
14 vector<int>g[10005],val[maxn];
15 char str1[maxn], str2[105];
16 void insert(char *str, int v){
17     int u = 0, len = strlen(str+1);
18     for (int i = 1; i <= len; i++){
19         int c = str[i] - \'a\';
20         if (!ch[u][c]){
21             memset(ch[sz], 0, sizeof ch[sz]);
22             val[sz].clear();
23             ch[u][c] = sz++;
24         }
25         u = ch[u][c];
26     }
27     val[u].push_back(v);
28 }
29 void bfs(){
30     int u = 0;
31     int head=0,tail=0;
32     for (int i = 0; i < sz_; i++){
33         int v = ch[u][i];
34         if (v){ fail[v] = 0; q[tail++] = v; }
35     }
36     while (head!=tail){
37         int u = q[head++];
38         for (int i = 0; i < sz_; i++){
39             int v = fail[u];
40             if (!ch[u][i])continue;
41             q[tail++] = ch[u][i];
42             while (v&&!ch[v][i])v = fail[v];
43             fail[ch[u][i]] = ch[v][i];
44         }
45     }
46 }
47 void ac(){
48     int u = 0;
49     for (int i = 1; i <= n; i++){
50         int c = str1[i] - \'a\';
51         while (u&&!ch[u][c])u = fail[u];
52         u=ch[u][c];
53         int ux = u;
54         while (ux){
55             for (int j = 0; j < val[ux].size(); j++)
56                 g[val[ux][j]].push_back(i - m[val[ux][j]] + 1);
57             ux = fail[ux];
58         }
59     }
60 }
61 int main(){
62     while (~scanf("%s", str1 + 1)){
63         n = strlen(str1 + 1);
64         scanf("%d", &k);
65         cnt = 0;
66         sz = 1; memset(ch[0], 0, sizeof ch[0]);
67         for (int i = 0; i <= 10004; i++)g[i].clear();
68         for (int i = 1; i <= k; i++){
69             scanf("%s", str2 + 1);
70             m[i] = strlen(str2 + 1);
71             insert(str2, i);
72         }
73         bfs();
74         ac();
75         for (int i = 1; i <= k; i++)cnt+=g[i].size();
76         printf("%d\n", cnt);
77         for (int i = 1; i <= k; i++)
78             for (int j = 0; j < g[i].size(); j++)
79                 printf(j == g[i].size() - 1 ? "%d\n" : "%d ", g[i][j]);
80         for (int i = 0; i <= sz; i++)val[i].clear();
81     }
82     return 0;
83 }      

View Code

KMP,AC自动机