KMP字符串(算法题)

在这里插入图片描述

#include <iostream>
using namespace std;

const int N = 100010, M = 1000010;

int n, m;       // n是模式串p的长度,m是主串s的长度
int ne[N];      // next数组,存储模式串的每个位置的最长公共前后缀长度
char s[M], p[N];// s是主串(长文本),p是模式串(待匹配字符串),下标均从1开始

int main() {
    // 输入模式串p(从下标1开始存储)和主串s
    cin >> n >> p + 1 >> m >> s + 1;

    /************ 构建next数组(核心:模式串自我匹配过程) ************/
    // ne[1] = 0,因为单个字符没有真前缀/后缀,直接从i=2开始计算
    for (int i = 2, j = 0; i <= n; i++) { 
        // 当j>0且p[i]与p[j+1]不匹配时,回退j到ne[j]的位置
        // 模拟:此时已匹配p[1..j],但p[i] != p[j+1],需缩短前缀长度
        while (j && p[i] != p[j + 1]) j = ne[j]; 

        // 如果当前字符匹配,j指针后移,扩展匹配长度
        if (p[i] == p[j + 1]) j++; 

        // 记录当前位置i的最长匹配前缀的结束位置j
        ne[i] = j; 
        // 模拟示例:例如p="ABCABD"
        // i=5时,j=2(前缀"AB"),p[5]='A'与p[3]='C'不匹配 → j回退到ne[2]=0
        // 然后p[5]='A'与p[1]='A'匹配,j=1 → ne[5]=1
    }

    /************ 在主串s中匹配模式串p ************/
    // i遍历主串s,j表示当前已匹配的模式串长度
    for (int i = 1, j = 0; i <= m; i++) { 
        // 当j>0且s[i]与p[j+1]不匹配时,利用next数组回退j
        // 模拟:主串s在位置i与模式串j+1不匹配,需将模式串右移
        while (j && s[i] != p[j + 1]) j = ne[j]; 

        // 当前字符匹配,j指针后移,继续匹配下一个字符
        if (s[i] == p[j + 1]) j++; 

        // 完全匹配:当j等于模式串长度n时,找到匹配位置
        if (j == n) { 
            // 计算起始位置:i - n + 1 - 1(因下标从1开始,输出从0开始的索引则需i-n)
            cout << i - n << ' '; 

            // 继续寻找下一个可能的匹配:利用next数组回退j
            j = ne[j]; 
            // 模拟示例:主串s="ABABABA", p="ABA"
            // 第一次匹配i=3时输出0,j回退到ne[3]=1 → 后续在i=5时再次匹配
        }
    }

    return 0;
}

本文参考了acwing算法基础课。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值