学习 KMP 算法

      KMP 算法是用来处理字符串匹配问题的。也就是给你两个字符串,你需要回答:B 串是否是 A 串的子串(或 B 串在 A 串中出现的位置)。比如,字符串 A = “ i am student ”, 字符串 B = “ student ”,我们就说 B 是 A 的子串。我们称待匹配的 A 串为匹配串,用来匹配的 B 串为模式串。

       如果使用普通的暴力枚举的算法,遇到个极端的例子,比如 abababababababaab 和 aab,匹配的时间复杂度会高到难以承受,为 O(nm),其中 n 为匹配串的长度,m 为模式串的长度。如果使用 KMP 算法,最坏的情况下,时间复杂度也只会是 O(n + m)。

(此处省略讲解过程,等以后再补Orz)

下面 KMP 算法的代码模板(注意,这里的 fail 数组是从 - 1 开始的)

 1 #include <bits/stdc++.h> 
 2 using namespace std;
 3 const int maxn = 1e6 + 9;
 4 
 5 string s, t;
 6 int fail[maxn];
 7 
 8 void get_fail(string x) {
 9     int i = 0, j = -1;
10     fail[0] = -1;
11     while (x[i]) {
12         if (j == -1 || x[i] == x[j]) {
13             fail[++i] = ++j;
14         } else {
15             j = fail[j]; 
16         }
17     }
18 }
19 
20 int kmp(string x, string y) {
21     get_fail(y);
22     int i = 0, j = 0, res = 0;
23     int m = y.size();
24     while (x[i]) {
25         if (x[i] == y[j]) {
26             ++i;
27             ++j;
28             if (!y[j]) {
29                 ++res;
30                 cout << i - m + 1 << endl;   // 输出模式串在匹配串中出现的位置(从1开始计数) 
31                 j = fail[j];                 // 匹配部分可以重叠,如果不可以重叠则直接 j = 0;
32             }
33         } else {
34             j = fail[j];
35             if (j == -1) {
36                 ++i;
37                 ++j;
38             }
39         }
40     }
41     return res;                              // 这里返回的 res 代表模式串在匹配串中出现的次数
42 }
43 
44 int main() {
45     cin >> s >> t; 
46     cout << kmp(s, t) << endl;
47     return 0;
48 }

猜你喜欢

转载自www.cnblogs.com/CIVAN-LXYAO/p/9464127.html