KMP算法求next和nextval代码原理

如果没有了解过KMP算法的话推荐阅读数据结构KMP算法配图详解(超详细)_哈顿之光的博客-CSDN博客_数据结构kmp算法前言KMP算法是我们数据结构串中最难也是最重要的算法。难是因为KMP算法的代码很优美简洁干练,但里面包含着非常深的思维。真正理解代码的人可以说对KMP算法的了解已经相当深入了。而且这个算法的不少东西的确不容易讲懂,很多正规的书本把概念一摆出直接劝退无数人。这篇文章将尽量以最简单的方式介绍KMP算法以及他的改进,文章的开始我先对kmp算法的三位创始人Knuth,Morris,Pratt致敬,懂得这...https://blog.csdn.net/weixin_46007276/article/details/104372119

上代码!!!

vector<int> GetNext(string str)
{
	int index = 0;		// 对str进行遍历时的索引
	int k = -1;		// next数组的值
	vector<int> next(str.length(), 0);		// 分配足够的空间并初始化
	next[0] = -1;		// 固定值
	
	while(index < str.length() - 1)
	{
		if(k == -1 || str[k] == str[index])
		{
			++k;
			++index;
			next[index] = k;
		}
		else
			k = next[k];
	}
    
    return next;
}

首先,我们要明白KMP算法的一些基本内容。

1、由于每一次最多增加一个字符,所以next[j+1]的最大值为next[j]+1。

2、重点:如果P_{k1} !\neq P_{j},那么next[j+1]可能的次大值为next[next[j]]+1,以此类推即可高效求出next[j+1]。

那么,我们来探索一下代码背后的原理,跟着代码走一遍

1.求next[j + 1],则一直next[1] 、next[2]......next[j](递归一下)

2.假如next[j] = k1,则P_{1}...P_{k1-1} = P_{j - k1 - 1}...P_{j - 1}(前k1 - 1位字符和后k1 - 1位字符是相等的)

3.如果P_{k1} = P_{j}P_{1}...P_{k1-1} P_{k1}= P_{j - k1 - 1}...P_{j - 1}P{j},则next[j + 1] = k1 + 1,否则进入下一步

4.假设next[k1] = k2,则有P_{1}...P_{K2} = P_{k1 - k2 + 1}...P_{k1 - 1}

5.由2、3,得:P_{1}...P_{k2-1} = P_{k1 - k 2 + 1}...P_{k1 - 1} = P_{j - k1 + 1}...P_{j - k1+k2-1}=P_{j - k2 + 1}...P_{j - 1},即这四段相等。

6.若P_{k2}=P_{j},则P_{1}...P_{k2} = P_{j - k2 + 1}...P_{j},即next[j + 1] = k2 + 1,否则重复4、5、6

图解上述过程:

        假如k = 7,next[k] = 3. j = 15

         我们可以看到,只需要对比str[7]和str[15]即可,若是相同的话则3成立,若不相同,那么

k = next[k] = 3

假设我们现在是这种情况,那么我们可以知道0--2 == 4--6

而0--7 == 8--14

所以4--6 == 12--14, 0--2 == 8--10

所以0--2 == 4--6 == 8--10 == 12--14

所以我们只需要对比 str[3]和str[15]地值,若是相同的话则3成立,不相同一直重复上述过程

理解了上面的原理,那么,求nextval数组的代码只需稍微修改一下即可

C++
vector<int> GetNextval(string str)
{
	int index = 0;		// 对str进行遍历时的索引
	int k = -1;		// next数组的值
	vector<int> nextva;(str.length(), 0);		// 分配足够的空间并初始化
	nextval[0] = -1;		// 固定值
	
	while(index < str.length() - 1)
	{
		if(k == -1 || str[k] == str[index])
		{
			++k;
			++index;
            if(str[index] != str[k])
			    nextval[index] = k;
            else
                nextval[index] = nextval[k]
		}
		else
			k = nextval[k];
	}
    
    return nextval;
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值