標籤:pre ++ ora 子串 lse 遇到 ++i cin 字串匹配
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 }
學習 KMP 演算法