串的模式匹配算法之KMP算法

了解各种关于串的存储结构信息欢迎点击此处,这里就不做赘述,直奔主题。

KMP算法

这种改进算法是由Knuth、Morris和Pratt同时设计完成的,因此简称为KMP算法。此算法可以在O(n+m)的时间数量上完成串的模式匹配操作。其改进在于:每当一趟匹配过程中出现字符比较不等时无需回溯 i 指针,而是利用得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。

KMP算法仅当模式与母串之间存在许多“部分匹配”的情况下,才显得比BF算法快得多。但是KMP算法的最大特点是指示母串的指针无需回溯,整个匹配过程中,对母串仅需从头至尾扫描一遍。这对处理从外设输入的庞大文件很有效,可以边读入边匹配,而无需回头重读。

下图为KMP算法的匹配过程

在这里插入图片描述

下图是利用模式的next函数进行匹配的过程示例

在这里插入图片描述

C++代码

#include<iostream>
using namespace std;
int next[50];
void get_next(string S,int next[])
{
	int i = 1;
	int j = 0;
	next[1] = 0;
	while( i < S.size() )
	{
		if( j==0 || S[i-1]==S[j-1] )//数组下标默认是0开始,第一次比较的位置是0/1,位置1对应着下标0的数据,所以得执行-1操作;
		{                           //另一种做法是修改字符串s的下标,往上提一位,即下标0不存数据 
			i++;                    
			j++;
			next[i] = j;
		}
		else
		j = next[j];
	}
}
int KMP(string S,string T,int pos)
{
	int i = pos;
	int j = 1;
	while( i <= S.size() && j <= T.size() )
	{
		if( j ==0 || S[i-1] == T[j-1] )//0下标有数据,故从0下标开始 
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	if( j > T.size() )
	return i - T.size();
	return 0;
}
int main()
{
	int pos;
	string s,t;
	while( true )
	{
		cout<<"请输入母串:";
		cin>>s;
		cout<<"请输入模式串:";
		cin>>t;
		get_next(t,next);
		cout<<"请输入在母串中开始寻找的位置(小于等于"<<s.size()<<"):";
		cin>>pos;
		while ( pos > s.size() )
		{
			cout<<"请重新输入在母串中开始寻找的位置(小于等于"<<s.size()<<"):";
			cin>>pos;
		}
		cout<<"模式串在自母串第 "<<pos<<" 位开始出现的位置为 "<<KMP(s,t,pos)<<endl<<endl;
	}
}

结果

请输入母串:fscjnceeskcufnmiercefecn
请输入模式串:ce
请输入在母串中开始寻找的位置(小于等于24):1
模式串在自母串第 1 位开始出现的位置为 6

请输入母串:fscjnceeskcufnmiercefecn
请输入模式串:ce
请输入在母串中开始寻找的位置(小于等于24):7
模式串在自母串第 7 位开始出现的位置为 19

请输入母串:ekuaskcrngmkncmxrucmcfucsrnkmxf
请输入模式串:cmc
请输入在母串中开始寻找的位置(小于等于31):32
请重新输入在母串中开始寻找的位置(小于等于31):31
模式串在自母串第 31 位开始出现的位置为 0

请输入母串:vybucknfaemxlusicbgtnfxmikcgnuml
请输入模式串:si
请输入在母串中开始寻找的位置(小于等于32):33
请重新输入在母串中开始寻找的位置(小于等于32):12
模式串在自母串第 12 位开始出现的位置为 15

请输入母串:

KMP算法和BF算法很相似,但KMP有一个next函数,重点也在这,要理解next函数值计算原理,后面还有一个next函数修正值,有问题可以评论留言。
欢迎各位大佬们指导小弟!
转载需说明!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

eeeasyFan

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

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

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

打赏作者

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

抵扣说明:

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

余额充值