# 看毛片就能AC算法

KMP && ACA

KMP:

 1  /**
2     freopen("in.in", "r", stdin);
3     freopen("right.out", "w", stdout);
4 */
5 //// /////////////////////////////
6 #include <cstdio>
7 #include <string>
8 #include <iostream>
9 using std::string;
10 const int N = 1000010;
11
12 int nex[N];
13
14 int main() {
15     freopen("in.in", "r", stdin);
16     freopen("right.out", "w", stdout);
17     string s, p;
18     std::cin >> s >> p;
19
20     nex[0] = 0;
21     for(int i = 1, j = 0; i < p.size(); i++) {
22         while(j && p[i] != p[j]) {
23             j = nex[j - 1];
24         }
25         if(p[i] == p[j]) j++;
26
27         /// while(j && p[i + 1] == p[j]) j = nex[j - 1];
28         /// 十分失败的优化，反例：
29         /// acccc
30         /// ccc
31         /// 001  :next
32         /// 可以看出能匹配两个串，但是这个优化只能算出一个来
33
34         nex[i] = j;
35     }
36
37     for(int i = 0, j = 0; i < s.size(); i++) {
38         while(j && s[i] != p[j]) {
39             j = nex[j - 1];
40         }
41         if(s[i] == p[j]) j++;
42         if(j == p.size()) {
43             printf("%d\n", i - j + 2);
44             j = nex[j - 1];
45         }
46     }
47
48     for(int i = 0; i < p.size(); i++) {
49         printf("%d ", nex[i]);
50     }
51
52     return 0;
53 }
KMP模板 洛谷P3375

例题：

A + B for you again

Period

Milking Grid

AC自动机

 1 #include <cstdio>
2 #include <string>
3 #include <iostream>
4 #include <queue>
5 #include <cstring>
6 const int N = 1000010;
7
8 using std::string;
9
10 struct AC {
11     int root, tot;
12     int tr[N][26], nex[N], ed[N];
13     bool vis[N];
14     AC() {
15         root = 1;
16         tot = 1;
17     }
18     void clear() {
19         for(int i = 1; i <= tot; i++) {
20             nex[i] = ed[i] = 0;
21             for(int j = 0; j < 26; j++) {
22                 tr[i][j] = 0;
23             }
24         }
25         return;
26     }
27
28     inline void insert(string x) {
29         int p = root;
30         for(int i = 0; i < x.size(); i++) {
31             int f = x[i] - 'a';
32             if(!tr[p][f]) {
33                 tr[p][f] = ++tot;
34             }
35             p = tr[p][f];
36         }
37         ed[p]++;
38         return;
39     }
40     void getnex() {
41         nex[root] = root;
42         std::queue<int> Q;
43         Q.push(root);
44         while(!Q.empty()) {
45             int x = Q.front();
46             Q.pop();
47             for(int i = 0; i < 26; i++) {
48                 int y = tr[x][i];
49                 if(y) {
50                     int j = nex[x];
51                     while(j != root && !tr[j][i]) {
52                         j = nex[j];
53                     }
54                     if(tr[j][i] && x != root) {
55                         j = tr[j][i];
56                     }
57                     nex[y] = j;
58                     Q.push(y);
59                 }
60             }
61         }
62         return;
63     }
64     int solve(string x) {
65         int ans = 0;
66         memset(vis, 0, (tot + 1) * sizeof(bool));
67         for(int i = 0, j = root; i < x.size(); i++)  {
68             int f = x[i] - 'a';
69             while(j != root && !tr[j][f]) {
70                 j = nex[j];
71             }
72             if(tr[j][f])  {
73                 j = tr[j][f];
74             }
75             if(ed[j] && !vis[j]) {
76                 ans += ed[j];
77                 vis[j] = 1;
78             }
79         }
80         return ans;
81     }
82 }ac;
83
84 int main() {
85     int n;
86     scanf("%d", &n);
87     string s;
88     for(int i = 1; i <= n; i++) {
89         std::cin >> s;
90         ac.insert(s);
91     }
92     ac.getnex();
93     std::cin >> s;
94     printf("%d", ac.solve(s));
95     return 0;
96 }

  1 #include <cstdio>
2 #include <string>
3 #include <iostream>
4 #include <queue>
5 #include <cstring>
6 const int N = 1000010;
7
8 using std::string;
9
10 struct Ans {
11     string s;
12     int cnt;
13 }a[N];
14
15 struct AC {
16     int root, tot;
17     int tr[N][26], nex[N], ed[N];
18     AC() {
19         root = 1;
20         tot = 1;
21     }
22     void clear() {
23         for(int i = 1; i <= tot; i++) {
24             nex[i] = ed[i] = 0;
25             for(int j = 0; j < 26; j++) {
26                 tr[i][j] = 0;
27             }
28         }
29         tot = 1;
30         return;
31     }
32
33     inline void insert(string x, int k) {
34         int p = root;
35         for(int i = 0; i < x.size(); i++) {
36             int f = x[i] - 'a';
37             if(!tr[p][f]) {
38                 tr[p][f] = ++tot;
39             }
40             p = tr[p][f];
41         }
42         ed[p] = k;
43         return;
44     }
45     void getnex() {
46         nex[root] = root;
47         std::queue<int> Q;
48         Q.push(root);
49         while(!Q.empty()) {
50             int x = Q.front();
51             Q.pop();
52             for(int i = 0; i < 26; i++) {
53                 int y = tr[x][i];
54                 if(y) {
55                     int j = nex[x];
56                     while(j != root && !tr[j][i]) {
57                         j = nex[j];
58                     }
59                     if(tr[j][i] && x != root) {
60                         j = tr[j][i];
61                     }
62                     nex[y] = j;
63                     Q.push(y);
64                 }
65             }
66         }
67         return;
68     }
69     void solve(string x) {
70         for(int i = 0, j = root; i < x.size(); i++)  {
71             int f = x[i] - 'a';
72             while(j != root && !tr[j][f]) {
73                 j = nex[j];
74             }
75             if(tr[j][f])  {
76                 j = tr[j][f];
77             }
78             int jj = j;
79             while(jj != root) {
80                 if(ed[jj]) {
81                     a[ed[jj]].cnt++;
82                 }
83                 jj = nex[jj];
84             }
85         }
86         return;
87     }
88 }ac;
89
90 int main() {
91     int n;
92     string x;
93     while(scanf("%d", &n) && n) {
94         ac.clear();
95         for(int i = 1; i <= n; i++) {
96             std::cin >> a[i].s;
97             ac.insert(a[i].s, i);
98         }
99         ac.getnex();
100         std::cin >> x;
101         ac.solve(x);
102         int large = -1;
103         for(int i = 1; i <= n; i++) {
104             large = std::max(large, a[i].cnt);
105         }
106         printf("%d\n", large);
107         for(int i = 1; i <= n; i++) {
108             if(a[i].cnt == large) {
109                 std::cout << a[i].s << std::endl;
110             }
111         }
112         for(int i = 1; i <= n; i++) {
113             a[i].cnt = 0;
114         }
115     }
116     return 0;
117 }

KMP与AC自动机的小差异：(在我的模板中)

KMP初始化的nex[0] = 0，而AC自动机的初始化nex[root]  =  root;

KMP中的nex[i]表示最长匹配数，是比下标多1的，而AC自动机中直接指向一个节点。

posted @ 2018-05-21 13:49  garage  阅读(...)  评论(...编辑  收藏