简介
对比朴素枚举,KMP 的思想是当匹配出现不一样的字符时,根据模式串当前子串的最大相同前后缀,将模式串的指针回退到最大相同前缀的末尾而非模式串的开头,从而优化时间复杂度。
记录子串最大相同前后缀长度的数组为 nexti。下图展示了 nexti 的求解过程。

Code
模板传送门
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10;
string s, t; int lens, lent, nxt[N];
void getNext() { for (int i = 1, j = 0; i < lent; i++) { while (j > 0 && t[i] != t[j]) j = nxt[j - 1]; if (t[j] == t[i]) ++j; nxt[i] = j; } }
void KMP() { int j = 0; for (int i = 0; i < lens; i++) { while (j > 0 && s[i] != t[j]) j = nxt[j - 1]; if (s[i] == t[j]) j++; if (j == lent) { printf("%d\n", i - lent + 2); j = nxt[j - 1]; } } }
int main() { cin >> s >> t; lens = s.size(); lent = t.size(); getNext(); KMP(); for (int i = 0; i < lent; i++) printf("%d ", nxt[i]); return 0; }
|