数据结构—KMP 算法:

news2024/10/24 18:16:47

算法思想:

KMP算法实现寻找主串中子串的位置时,主串指针地址不回退,在比对过程中串仅仅遍历一次,子串的回退可以是与当前主串可重新最多匹配的地址位置。

BF与KMP算法比对:

KMP

BF

主串不用回退

主串回退,回退到此次开始比较的下一位置

子串的回退可以是与当前主串可重新最多匹配的地址位置

子串回退到开始位置

思路展示:

1、首先遍历主串中与子串一致的字符,直至出现无法匹配:

如图:主串与子串的粉色阶段相同,而后面的无法匹配

2、当我们发现,在主串与子串相同的部分内,主串后一部分与子串前一部分相同

如图:主串与子串紫色部分相同

可以设想一下,子串是否可以从紫色结尾的地方重新和主串的当前位置再次做匹配

3、由步骤一则知道,主串与子串粉色部分相同,步骤二引入紫色部分相同,则可以推导出:

推导出:子串的前一部分与子串的后一部分相等

4、由思路推出表达式:

  • 子串此次匹配的结束地址下标位置为 j;
  • 开始下标:0;
  • 紫色结束下标:k-1;
  • 由紫色部分长度、字符都相等,所以长度: k-1-0=j-1-紫色开始下标;
  • 所以紫色开始下标:j-k;

结论:

匹配成功的子串片段中,寻找两个最长且相等的真子串,真子串长度决定子串返回的地址下标

真子串特点:

  1. 一真子串以子串的开头为开头
  2. 另一真子串以子串匹配片段的结尾为结尾
  3. K为子串的长度,也是子串在匹配失败时需要返回的位置

next数组及其练习(重点)

我们由上一个结论所得的K 值,保存得到的数组(next数组)

固定值:

        next[0]=-1;    next[1]=0;

易错:

        1、子串的截断字符不包含在此次子串片段范围内,当前的截断字符的next数组值,由截断前的所有字符作为判断决定

请判断:

        红色为标准错误,绿色为正确答案

        2、子串的真子串比对容易漏掉最长真子串

        红色为标准错误,绿色为正确答案

练习例子:

1:"abacdabcabaae"

      -1001001201231

2:"abacdabcabcde"

      -1001001201200

寻找next[]的固定规律:

  • 当我们已知下标为i 的next数组的值时:next[i]=k;
  • 需要判断子串str[]:str[k] 与 str[i] 是否相等?
  1. 相等: next[++i]=++k;
  2. 不相等:

        此时问题则迭代成为在当前已经遍历的字符串中寻找最长的相等真子串

                ->求当前 str[i+1] 对应的 next数组值

                ->即为 next[k]对应的next数组值

                -> next[++i]=next[k]

KMP算法的实现:

#include <iostream>
#include <string>
#include<assert.h>
using namespace std; 

//KMP 算法,i 不回退
//思路:
//下标: j-k ...j-1 = 0...k 
//找子串的两个最长真子串!首位两个真子串
//真子串长度为k;(next 数组)
//!注意,当前位置为截断不等位置,此位置的前一个位置为尾


int BF(const char* str1, const char* str2, int pos)
{
	assert(str1 != NULL && str2 != NULL);
	int len1 = strlen(str1);
	int  len2 = strlen(str2);

	int* next = (int*)malloc(sizeof(int) * len1);
	next[0] = -1;
	next[1] = 0;
	int i = 1;
	int k = 0;
	while (i+1 < len1)
	{
		
		if ((k == -1) || str1[i] == str1[k])
			next[++i]= ++k;
		else
			k=next[k];
	}

	if (pos < 0||pos>=strlen(str1)||str1==NULL||str2==NULL)
		return -1;

	int j = 0;
	i = pos;
	while(i<len1&&j<len2)
	{
			if ((j==-1)||(str1[i] == str2[j]))
			{
				i++;
				j++;
			}
			else
			{
				//KMP 算法:i保留在当前位置,与j 再次比较
				j = next[j];
				/*BF 算法:j = 0;  i = i - j + 1;*/
			}
	}
	if (j == len2)
		return i - j;
	return -1;
}

int main()
{
	const char *str1 = "ababcabcdabcdeabcdabcdd";
	//const char* str1 = "abcd";
	const char* str2 = "abcd";
	int i = 0;
	int j =0;
	j = BF(str1, str2, j);
	while(j!=-1)
	{
		 j = BF(str1, str2, j);
		printf("返回类比pos位置:%d\n", j);
		if (j == -1)
			break;
		j += strlen(str2);
	}
	return 0;
}

时间复杂度:

  1. KMP:O(m+n);主串只遍历一次
  2. BF: O(m*n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1497847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【npm】node包管理工具npm的介绍和基础使用

简言 npm 是 Node.js 的 包管理器&#xff08;Package Manager&#xff09;&#xff0c;它是专门用于管理 Node.js 项目中第三方库的工具。 本文介绍下npm和其使用方法。 npm介绍 npm 是世界上最大的软件注册中心。各大洲的开源开发者都使用 npm 共享和借用软件包&#xff…

【开源】SpringBoot框架开发陕西非物质文化遗产网站

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 设计目标2.2 研究内容2.3 研究方法与过程2.3.1 系统设计2.3.2 查阅文献2.3.3 网站分析2.3.4 网站设计2.3.5 网站实现2.3.6 系统测试与效果分析 三、系统展示四、核心代码4.1 查询民间文学4.2 查询传统音乐4.3 增改传统舞…

好书安利:《大模型应用开发极简入门:基于GPT-4和ChatGPT》这本书太好了!150页就能让你上手大模型应用开发

文章目录 前言一、ChatGPT 出现&#xff0c;一切都变得不一样了二、蛇尾书特色三、蛇尾书思维导图四、作译者简介五、业内专家书评总结 前言 ​如果问个问题&#xff1a;有哪些产品曾经创造了伟大的奇迹&#xff1f;ChatGPT 应该会当之无愧入选。仅仅发布 5 天&#xff0c;Chat…

服务器严重不够啊

必需采购服务器了&#xff0c;

JavaScript——流程控制(程序结构)

JavaScript——流程控制&#xff08;程序结构&#xff09; 流程控制就是来控制我们的代码按照什么结构顺序来执行。更倾向于一种思想结构。 流程控制分为三大结构&#xff1a;顺序结构、分支结构、循环结构 1、顺序结构 ​ 代码从上往下依次执行&#xff0c;从A到B执行&#x…

K线形态分析宝典:10种K线形态特征与应用场景详解,助您投资更有底气

在金融市场中&#xff0c;K线图是投资者们最常用的技术分析工具之一&#xff0c;通过观察K线形态可以揭示市场的走势和情绪。以下是10种常见的K线形态&#xff0c;包括详细的形态特征、作用以及应用场景&#xff0c;帮助您更好地理解市场走势&#xff0c;制定更精准的投资策略。…

springboot实现多线程开发(使用@Async注解,简单易上手)

根据springboot的核心思想便捷开发&#xff0c;使用多线程也变得简单起来&#xff0c;通过一下几个步骤即可实现。 核心注解 EnableAsync将此注解加在启动类上&#xff0c;使项目支持多线程。 Async 使用我们的Async注解在所需要进行多线程的类上即可实现。 配置线程池 …

cefsharp(winForm)调用js脚本,js脚本调用c#方法

本博文针对js-csharp交互(相互调用的应用) (一)、js调用c#方法 1.1 类名称:cs_js_obj public class cs_js_obj{//注意,js调用C#,不一定在主线程上调用的,需要用SynchronizationContext来切换到主线程//private System.Threading.SynchronizationContext context;//…

2024年需要重点关注的15种计算机病毒

2024年&#xff0c;计算机病毒威胁变得愈发多元化和复杂化。涉及勒索病毒、二维码病毒、挖矿木马等15种类型&#xff0c;这些病毒从数据勒索到系统入侵&#xff0c;对全球网络安全构成严峻挑战。不同传播方式如社交媒体、移动介质、网页、短信等使得设备容易受到感染。同时&…

vue基础教程(4)——深入理解vue项目各目录

博主个人微信小程序已经上线&#xff1a;【中二少年工具箱】。欢迎搜索试用 正文开始 专栏简介1. 总览2. node_modules3.public4.src5.assets6.components7.router8.stores9.views10.App.vue11.main.js12.index.html 专栏简介 本系列文章由浅入深&#xff0c;从基础知识到实战…

【Linux篇】gdb的使用

&#x1f49b;不要有太大压力&#x1f9e1; &#x1f49b;生活不是选择而是热爱&#x1f9e1; &#x1f49a;文章目录&#x1f49a; 1. 背景知识2. 使用 1. 背景知识 1. 程序发布的方式有两种&#xff0c;debug模式和release模式 2. Linux下&#xff0c;gcc和g编译生成的可执行…

AI新工具 MacOS 翻译提供翻译、润色和语法修改功能的插件;AI生成 Excel公式;Deepmind前华人员工创建视频生成工具

1: OpenAI Translator Bob Plugin macOS 平台的翻译提供翻译、润色和语法修改功能的插件 OpenAI Translator Bob Plugin是一款基于OpenAI的API&#xff0c;为用户提供翻译、润色和语法修改功能的插件。这款插件专门为macOS平台上的Bob软件设计&#xff0c;通过使用先进的Chat…

3.6 day1 FreeRTOS

1.总结keil5下载代码和编译代码需要注意的事项 注意要将魔术棒的的debug选项中的setting中的flashdownload中的reset and run 勾选上&#xff0c;同时将pack中的enable取消勾选 2.总结STM32Cubemx的使用方法和需要注意的事项 可以通过功能列表对引脚进行设置&#xff0c;并且可…

FreeRTOS day2

1.使用ADC采样光敏电阻数值&#xff0c;如何根据这个数值调节LED灯亮度。 while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */adc_value HAL_ADC_GetValue(&hadc);TIM3->CCR3 adc_value * 999 / 4095;printf("%d %d\r\n",adc_value,TIM3->C…

URL输入到页面渲染过程详解

当我们在浏览器中输入一个URL并按下回车键时&#xff0c;浏览器会执行一系列步骤来解析URL、发送请求、接收响应&#xff0c;并最终渲染页面。这个过程涉及到多个阶段&#xff0c;包括DNS解析、TCP握手、发送HTTP请求、服务器处理请求、返回HTTP响应、浏览器解析和渲染等。下面…

安卓手机如何使用JuiceSSH实现公网远程连接本地Linux服务器

文章目录 1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? cpolarJuiceSSH 实现手机端远程连接Linux虚拟机(内网穿透,手机端连接Linux虚拟机) …

14. C++继承与虚函数

【继承基础概念】 继承可以让本类使用另一个类的非私有成员&#xff0c;提供共用成员的类称为父类或基类&#xff0c;使用共用成员的类称为子类或派生类&#xff0c;子类创建对象时会包含继承自父类的成员。 继承的优势是减少重复定义数据&#xff0c;当本类需要在另一个类的…

变量提升,函数提升

一、变量提升 只有var存在变量提升。变量提升就是将变量提至当前作用域的最前面&#xff0c;只提升声明&#xff0c;不提升赋值。 console.log(n) // undefined&#xff0c;不会报错 var n 10 等价于 var n console.log(n) // undefined&#xff0c;不会报错 n 10 因为n是…

【Spring底层原理高级进阶】Spring Batch清洗和转换数据,一键处理繁杂数据!Spring Batch是如何实现IO流优化的?本文详解!

&#x1f389;&#x1f389;欢迎光临&#xff0c;终于等到你啦&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;持续更新的专栏《Spring 狂野之旅&#xff1a;从入门到入魔》 &a…

算法题 — 三个数的最大乘机

三个数的最大乘机 整型数组 nums&#xff0c;在数组中找出由三个数字组成的最大乘机&#xff0c;并输出这个乘积。&#xff08;乘积不会越界&#xff09; 重点考察&#xff1a;线性扫描 排序法&#xff1a; public static void main(String[] args) {System.out.println(so…