0%

KMP

简介

对比朴素枚举,KMP 的思想是当匹配出现不一样的字符时,根据模式串当前子串的最大相同前后缀,将模式串的指针回退到最大相同前缀的末尾而非模式串的开头,从而优化时间复杂度。

记录子串最大相同前后缀长度的数组为 nextinext_i。下图展示了 nextinext_i 的求解过程。

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;
}