KMP算法的自己体会和实现

数据结构讲到字符串匹配的时候,讲到了一个很优秀的算法——KMP算法!
相对于传统的匹配算法,KMP算法有自己的一定优势。当字符串中有很长的一段重复字符的时候,可以省略过很大的一部分无效比较。跟传统的匹配算法不同的是,KMP算法引进了一个新的东西—— 跳转表,就是这个表在匹配时发挥了巨大的作用。

这是课本上的原理与例子,我加上了一些自己的理解。所以最重要的是得出跳转表next[]来辅助我们匹配字符串。首先是第一种匹配表:

void get_nextval1(string a,int next[])
{
	next[0] = -1;
	int i = 0;//前缀,不回溯
	int j = -1;//模式串回溯
	while (i < a.length() - 1)
	{
		if (j == -1 || a[i] == a[j])
		{
			++i;
			++j;
			next[i] = j;
		}
		else
			j = next[j];
	}
} 


这种版本的跳转表还有一个问题就是前面有很多的字符相同的时候,仍得一个一个匹配,所以经过改进有了第二种改进版的跳转表:

void get_nextval2(string a, int next[])
{
	next[0] = -1;
	int i = 0;//前缀,不回溯
	int j = -1;//模式串回溯
	while (i < a.length() - 1)
	{
		if (j == -1 || a[i] == a[j])
		{
			++i;
			++j;
			if (a[i] == a[j])
				next[i] = next[j];
			else
				next[i] = j;
		}
		else
			j = next[j];
	}
}


这种跳转表就很好的回避了那个问题,当相同的时候会滑过那一串,具体的例子如下图:


(嗯,图片斜着是为了治大家的颈椎病的。。。)

其实,KMP算法的思路很好理解,但是在实现的时候如果把数据结构书上的代码写进去会发现各种越界,这就是另一个问题了,在数据结构中,第一个位置被默认存放了字符串的长度,所以在写为代码的时候,应该使用length函数得到长度,而且所有的位置都应比书上少1!

最后上主函数和KMP函数。。。

int main()
{	
	int a[100];
	string partern;//模式字符串
	string search;//匹配字符串
	cout << "请输入模式字符串:";
	cin >> partern;
	cout << "请输入匹配字符串:(匹配字符串应长于模式字符串!)";
	cin >> search;
	get_nextval2(partern,a);
	if (kmp(search, partern, a))
		cout << "匹配成功!" << endl;
	else
		cout << "匹配失败!" << endl;

	return 0;
}

int kmp(string a, string b, int next[])//a为匹配字符串,b为模式字符串
{
	int i = 0;
	int j = 0;
	while (i < a.length())
	{
		if (j == -1 || a[i] == b[j])
		{
			++i;
			++j;
		}
		else
			j = next[j];
	}
	if (j == b.length())
		return i - b.length();
	else
		return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值