[luoguP3375] KMP
题意
KMP 板子题
sol
考虑通过移动 \(s2\) 的方式来匹配 \(s1\)。
如果当失配时,就将 \(s2\) 右移一位后再重新匹配就太浪费了,考虑如果已经匹配的部分的一组前后缀相同的话,就相当于这一部分已经完全匹配过,因此可以直接将 \(s2\) 的相同的前后缀的长度与 \(s1\) 中的对应位置对齐,因此只需要计算出 \(s2\) 的前 \(i\) 项的相同前后缀长度即可。
计算该长度相当于使用 \(s2\) 对 \(s2\) 进行匹配,因此代码基本相同
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1000005;
int n, m;
char s[N], t[N];
int ne[N];
int main(){
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1), m = strlen(t + 1);
for (int i = 2, j = 0; i <= m; i ++ ) {
while (j && t[i] != t[j + 1]) j = ne[j];
if (t[i] == t[j + 1]) j ++ ;
ne[i] = j;
}
for (int i = 1, j = 0; i <= n; i ++ ) {
while (j && s[i] != t[j + 1]) j = ne[j];
if (s[i] == t[j + 1]) j ++ ;
if (j == m) printf("%d\n", i - m + 1);
}
for (int i = 1; i <= m; i ++ ) printf("%d ", ne[i]);
}

浙公网安备 33010602011771号