KMP算法

KMP算法是一种高效的字符串匹配算法,避免了暴力法中的回溯问题。通过构建next数组,当匹配失败时,模式串能直接跳到有效位置继续匹配。文章提供了KMP算法的基本实现代码及next数组的计算方法,并展示了具体的应用例子。
摘要由CSDN通过智能技术生成

KMP算法

如何选择算法的关键就在于先看暴力法如何做,再去想哪种算法能够优化他

KMP是什么

一种字符串匹配算法,用于查找一个模板字符串在一串长文本里每次出现的起始下标,类似于crtl+f的功能

假设有数组长文本K[N],模板P[M]

暴力法对字符串匹配:设i作为K的下标,j作为p的下标,当K[i]与 P[0]相等时,开始匹配下个字符,否则让i++,如果连续匹配到很多个字符,但突然有一个不匹配,那么i与j都会回溯,比如K[i]和P[0]相等了,一直匹配到K[i + random],P[j + random]时匹配失败,那么i,与j都会回溯,K的下标i + random回溯到i++,j + random回溯到j = 0

KMP算法就是针对这一暴力法进行优化,使得i无需回溯。通过修改j 的位置,让模式串P尽量地移动到有效的位置。

因此需要一个next数组使模式串能够快速移动,如果P[j]时失配了,那么就根据j对应的next[j] 使模式串跳跃,如果next[j] 为0 或 - 1,那么就跳到模式串开头位置,反之,则跳过next[j]个字符,继续匹配

对于如何求出next对应的值,可以看 从头到尾彻底理解KMP,串的next数组怎么算

可得到基本实现代码

int KMPsearch(char* s, char* p)
{
	int i = 0, j = 0;
	int slen = strlen(s);
	int plen = strlen(p);

	while (i slen && j < plen)
	{
		if (j == -1 || s[i] == p[j]) i++, j++;
		else j = next[j];
	}

	if (j == plen) return i - l;
	else return -1;
}

以及求得next数组代码

void GetNext(char* p, int ne[])
{
	int plen = strlen(p);
	ne[0] = -1;
	int k = -1;
	int j = 0;
	while (j < plen - 1)
	{
		if (k == -1 || p[j] == p[k])
		{
			++k, ++j;
			if (p[j] != p[k])
				ne[j] = k;
			else ne[j] = ne[k];
		}
		else k = ne[k];
	}
}

具体的模式串跳跃展示

在这里插入图片描述

开始匹配时

s[0] == p[0],s[1] == p[1], 但是s[2] != p[2]

此时j = 2,看next[2]为多少,将模式串跳跃过next[2]个字符

例题代码(yxc做法)

在这里插入图片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>

using namespace std;

const int N = 10010;
const int M = 10010;

int n, m;
char p[N], s[M];
int ne[N];
int main()
{
	cin >> n >> p + 1 >> m >> s + 1;

	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 + 1);//n或j都可以
				j = ne[j];
			}
			
		}
	}

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涅槃豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值