AcWing 831. KMP字符串匹配

题目


暴力

在S内查找P
如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置,则有:

如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯,j 被置为0


KMP 思路

在这里插入图片描述

在S内查找P

  • 无论S是什么,P字符串都会存在一个next[]数组,记录最大前缀和后缀相等的字符个数
  • 然后比较S P时,发现S[7] 和 P[7]不一样, a ≠ c,
  • 那么我们让j回退, j = next[j] ,
  • 注意 我们比较的是 P[i] 和 S[j+1], 所以 j = = 6 ,也就是 j = next[6[ = 4
  • 然后j就在P内回退到位置4 ,指向b
  • 然后再让j往后移动,此时j指向P中位置5的元素 a,
  • 再和S中的i 比较 c 和 a

注意

  • KMP匹配,是S与P匹配
  • next[]数组,求字串P最大前缀和后缀相等的个数

代码

(思路是这样,但是这个题后来数据范围改了,不通过了)

#include <iostream>

using namespace std;

const int M = 1e4 + 10, N = 1e5 + 10;

int m, n;
char p[M], s[N];
int ne[M];
//

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

    //求ne数组
    for(int i = 2, j = 0; i <= m; 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 <= n; i++) {
        while(j && s[i] != p[j + 1]) j = ne[j];
        if(s[i] == p[j + 1]) j++;
        if(j == m) {
            j = ne[j]; //当匹配成功时继续往下匹配
            printf("%d ", i - m);
        }
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值