[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]);
}
posted @ 2025-03-27 22:05  是一只小蒟蒻呀  阅读(11)  评论(0)    收藏  举报