首页 > 编程语言 >KMP算法解释:理解关于next[j]数组的求解问题

KMP算法解释:理解关于next[j]数组的求解问题

时间:2022-12-24 16:13:11浏览次数:31  
标签:string int Pattern length next 算法 KMP

一、算法背景介绍(我们为什么要采用这种算法?)
1.补充定义:
(1)主串:待匹配的大字符串
(2)模式串:我们希望在主串中匹配到的字符串
2.从暴力匹配到KMP算法
(1)暴力匹配算法
谈到KMP算法,离不开比较的是我们的暴力匹配算法,即从主串和模式串第一个字符开始比较,当出现失配时,我们将模式串中的比较字符回到第一位,主串回溯到开始比较的字符的下一位。代码如下。

点击查看代码
int IndexString(char* Original_string, char* Pattern_string) {
	int length_OriStr = strlen(Original_string);
	int length_PatStr = strlen(Pattern_string);
	for (int i = 0; i < length_OriStr; ) {//for循环相比while更加直观,两个终止条件均为不到字符串终点
		for (int j = 0; j < length_PatStr; ) {
			if (*(Original_string + i) == *(Pattern_string + j)) {
				i++;
				j++;
			}
			else {//失配
				j = 0;
				i = i - j + 1;
			}
			if (j == length_PatStr) {
				return i - j;//返回匹配的字符串在主串中第一个相同字符的下标。
			}
		}
	}
	return False;//未找到
}
(2)对暴力匹配算法进行分析,容易知道它的时间复杂度为O(m*n),m为主串长,n为模式串长,其时间复杂度较高,为此有时间复杂度更低的kmp算法。

二、算法的具体实现(附代码)
1.关于串的定义

点击查看代码
#define True 1
#define False 0

typedef int status;

typedef struct {
	char* string;
	int length;
}HString;
2.求解next[j]数组
点击查看代码
status Getnext(int* next,HString Pattern_string) {//得到nextj数组
	if (next == NULL) {
		return False;
	}
	next[0] = -1;
	int k = next[0];//k用来存放对应next[j]
	int j = 0;
	while (j < Pattern_string.length-1) {
		//因为最后会有j++,所以要有length-1,否则超限;或者理解为每次都在求解当前位置对应下一位置的next[j]值,所以要-1
		if (k == -1 || *(Pattern_string.string + k) == *(Pattern_string.string + j)) {//没有匹配字符或当前两个字符相等
			j++;
			k++;
			next[j] = k;//后一个的nextj=前一个nextj+1
		}
		else {
			k = next[k];//回溯
		}
	}
	return True;
}
3.使用生成的next数组进行模式串匹配
点击查看代码
int Index(HString Original_string, HString Pattern_string) {
	int judge = -1;//标识符,默认模式串不存在
	int i = 0, j = 0;//i用来遍历主串,j用来跳转模式串
	int numx = 0;//用来保存每个第一次比较的字符在主串中的位置

	int* next = (int*)malloc(sizeof(int) * Pattern_string.length);//nextj数组
	if (next == NULL) {
		exit(1);
	}
	Getnext(next, Pattern_string);//调用上面的函数求得模式串next[j]数组

	for (i = 0; i < Original_string.length; ) {
		if (j==-1 || *(Original_string.string + i) == *(Pattern_string.string + j)) {
			i++;
			j++;
			if (j == Pattern_string.length) {//完全相同后跳出
				break;
			}
		}
		else {
			j = *(next+j);//跳转到next[j]对应位置
		}
	}
	if (j == Pattern_string.length) {
		judge = i - j + 1;//返回完全匹配后,模式串中第一个字母在主串第一次出现的次序(不是下标)
	}
	free(next);
	return judge;
}

三、算法的理论推导
写了四页纸,比较草,抽空整理一下传上来。
四、算法总结
1.算法步骤:
(1)先进行模式串“自己和自己的比较”,以此求得next[j]数组,从而在后续的主串与模式串匹配中直接跳跃,避免重复性的“自己和自己比较”。
(2)然后利用next[j]数组进行比较
2.评价:经典算法,算是学到的第一个理解透彻比较困难的算法,自己进行推导有助于理解,理解后算法不需要死记硬背即可写出。

标签:string,int,Pattern,length,next,算法,KMP
From: https://www.cnblogs.com/chfanyang/p/16840646.html

相关文章

  • 基于随机森林算法进行硬盘故障预测
    摘要:本案例将带大家使用一份开源的S.M.A.R.T.数据集和机器学习中的随机森林算法,来训练一个硬盘故障预测模型,并测试效果。本文分享自华为云社区《基于随机森林算法进行硬盘......
  • 每日算法之数组中只出现一次的两个数字
    JZ56数组中只出现一次的两个数字题目一个整型数组里除了两个数字只出现一次,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字思路算法实现既然有两个数......
  • 基于K-means聚类算法进行客户人群分析
    摘要:在本案例中,我们使用人工智能技术的聚类算法去分析超市购物中心客户的一些基本数据,把客户分成不同的群体,供营销团队参考并相应地制定营销策略。本文分享自华为云社区《​......
  • 基于K-means聚类算法进行客户人群分析
    摘要:在本案例中,我们使用人工智能技术的聚类算法去分析超市购物中心客户的一些基本数据,把客户分成不同的群体,供营销团队参考并相应地制定营销策略。本文分享自华为云社区《......
  • 算法--分治算法
    分治算法 一、算法思想  分治法作为一种常见的算法思想,其概念为:把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题,直到最后子问题可以......
  • 基本形态学算法
    基本形态学算法为什么要做基本形态学算法的研究和实现?是因为形态学是一个非常有力,应用广泛的工具,但同时也是研究不是很清楚的工具。往往一个恰到好处的变换,就能......
  • 关于 贪心算法 知友们的看法
    贪心算法的产生背景是什么?它主要解决的是哪一类的问题?这些问题可以总结成一个固定的什么样的模型?产生背景没了解过,但是我以前学建模的时候是这样理解的:贪心算法是一种思......
  • 95% 的算法都是基于这 6 种算法思想!!!
     https://zhuanlan.zhihu.com/p/431240843 1递归算法1.1算法策略1.2适用场景1.3使用递归算法求解的一些经典问题   DOM树为例 2分治算法......
  • 【随机接入】基于随机接入代价的异构网络速率分配算法
    1.软件版本matlab2013b2.本算法理论知识在协作传输中,把业务流分拆到不同网络进行传输可解决单一网络无法传输的问题,同时降低接入阻塞率并提高网络利用率。随机接入......
  • 代码随想录算法训练营Day21|530. 二叉搜索树的最小绝对差、501. 二叉搜索树中的众数、
    代码随想录算法训练营Day21|530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236.二叉树的最近公共祖先530.二叉搜索树的最小绝对差530.二叉搜索树的最小绝对......