KMP 是可以在文本串s中快速查找模式串p的一种算法。
部分匹配表
pmt[i] 就是,从 p[0] 往后数、同时从 p[i] 往前数相同的位数,在保证前后缀相同的情况下,最多能数多少位。(但要 小于 p的长度)
线性规划题,真前缀后缀的前缀和都往后添加。
故而可以用前缀去匹配后缀。
此过程还可以顺带求出前面的部分匹配表,即失配后往前移动模式串到未失配且最优时,
正确且复杂度为 O(2n)
匹配
若失配,则直到模式串成功匹配或移到头时继续。
因为每当 j 往后移了,则之后 i 必定往后移动(部分决定 j 到底可以往前移几位),
算法正确,且时间复杂度为 O(2n)
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, m;
int pmt[N];
char p[N], s[N];
int main()
{
scanf("%d%s%d%s", &n, p, &m, s);
for (int i = 1, j = 0; i < n; pmt[i ++ ] = j)
{
while (j && p[i] != p[j]) j = pmt[j-1]; // 不匹配
if (p[i] == p[j]) j ++; // 匹配就往前走
}
for (int i = 0, j = 0; i < m; i ++ )
{
while (j && s[i] != p[j]) j = pmt[j-1];
if (s[i] == p[j]) j ++;
if (j == n)
{
printf("%d ", i - j + 1);
j = pmt[j-1];
}
}
return 0;
}