大佬讲解的KMP字符串问题,感觉代码巨简单

本文算法思路来自yxc大佬,这里仅仅只是照抄了一遍方便复习。

问题描述:给定一个字符串S,以及一个模式串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串P在字符串S中多次作为子串出现。求出模式串P在字符串S中所有出现的位置的起始下标。
KMP的主要思想就是利用next数组来简化复杂度(建议记住以下例子方便回忆):
P字符串abababc(这里设置真正的索引从1开始)
索引为 1 2 3 4 5 6 7
nt数组 0 0 1 2 3 4 0
S字符串abaababcbabababc

// 匹配过程如下:
S:abaa...
P:abab...
跳到nx[3]=1(j=ne[j])索引处,然后比较P(j+1)和当前S[i]值(还是想找到快捷途径)
abaa...
--ab...
跳到nx[1]=0(j=ne[j])索引处,然后比较P(j+1)和当前S[i]值(找不到快捷途径了,只能从头匹配整个P)
abaababcbabababc
---abaa...
跳到nx[3]=1(j=ne[j])索引处,然后比较P(j+1)和当前S[i]值(还是想找到快捷途径)....
...
(每次匹配的时候i一直往前移动,只有j一直想找到最优的移动方式)

// 求next数组的过程
直接认为ne[1] = 0,从2开始求next方式和kmp过程类似(可以用例子abababc模拟一下得到nt数组: 0 0 1 2 3 4 0)

#include
using namespace std;
const int N = 1000010, M = 10000010;
int n, m;
char p[N], s[M];
int ne[N];

int main(){
cin >> n >> p + 1 >> m >> s + 1;

// 求next的过程
for(int i = 2, j = 0; i <= n; ++i){
    while(j && p[i] != p[j + 1]) j = ne[j];
    if(p[i] == p[j + 1]) j++;
    ne[i] = j;
}

// kmp匹配过程
for(int i = 1, j = 0; i <= m; ++i){
    while(j && s[i] != p[j + 1]) j = ne[j];
    if(s[i] == p[j + 1]) j++;
    if(j == n){
        printf("%d ", i - n);
        j = ne[j];
    }
}

}
这个过程还是比较抽象的,现阶段先尽量保持记忆吧

posted @ 2025-11-19 09:23  XShuang0101  阅读(15)  评论(0)    收藏  举报