KMP超高效匹配算法

news2024/11/27 6:42:24

简介:

        KMP算法是一种改进的字符串匹配算法,其中,KMP算法的运用核心是利用匹配失败后的信息,最大进度的减少模式串与目标串的匹配次数以达到快速匹配的效果。算法与暴力求解的改进在于每当一趟匹配过程中出现的字符比较不相等时,指向目标串的指针不在回到"原点",而是利用已经得到的”部分匹配“的结果将模式串向右移动最大且和目标串已匹配的距离后进行比较,总的来说就是目标串不回退,模式串回退,直到结束为止。

KMP实现如图:

        在图中,第一次比较不成功时,i= 3,j = 3,此时,i指针不变,需要将模式串向右移动两个字符的位置,继续进行i = 3,j = 1的下一趟比较;第二趟匹配中,前四个字符比较成功,但i = 7, j = 5时比较失败,此时将模式串向右移动3个字符的位置,继续进行i = 7,j = 2的下一趟比较,直至比较成功。

        注意,在整套算法体系中,指向目标串的指针i不会退,因此,一旦模式串在某个位置匹配失败后就要回退到某个位置与目标串继续进行匹配。


模式匹配:

        然而,在此,我们可发现,KMP算法中难点就在于模式串在匹配失败后要回退的位置。

        目标串的每个元素都要进行模式匹配,因此,当模式串的每个元素都有一个回退某个具体位置的指标,我们用next整型数组进行存储,即next[j] = k(j模式串的具体位置,k 为回退到模式串的具体位置)。

其中,k的值是这样规定的:

        1,规则:找到匹配成功部分的两个相等的真子串(注意:不包含本身,因为本身还要进行匹配),一个以下标0开始,另一个以j - 1下标结尾,即模式串的头部和尾部(原因可思考一下)。

        2,不管什么数据next[0] = -1;next[1] = 0;在这里,我们以下标来开始,而说到的第几个是从1开始。

下面我们运用以上原理来求模式串的next数组:

        


       以上的定位数组next的定位一定要根据模式串与目标串前后匹配成功的最大次数来定,而具体的匹配是根据模式串的前面和目标串的某个可以与之匹配的最大次数。

        到这里,我们手动求解定位数组next问题不大,那么,接下来要怎么用代码来求解呢?首先,我们先来观察已知条件,在求解next[i + 1]中,我们已知next[i]  = k;如果我们能够通过next[i]的值,再根据数学转换得到next[i + 1]的值,那么就能够实现整个数组的内容。

        首先,已知数组next[i] = k成立,具体的实现next数组我用图形的形式跟大家来演示:

接下来我用C代码的形式来演示一遍定位数组的求解:

//next代表定位数组,a代表模式串,lena代表模式串的长度
void Next(int* next, char* a, int lena)
{
	next[0] = -1;
	next[1] = 0;
	int j = 2, k = 0;
	while (j < lena) {
		if (k == -1 || a[k] == a[j - 1]) {
			next[j] = k + 1;
			j++;
			k++;
		}
		else
		{
			k = next[k];
		}
	}
}

        其中,定位数组算法的时间复杂度效率为O(lena)

具体运用代码如下:

int KMP(char* str, int strlen, char* a, int alen, int* next)
{
	assert(strlen || alen);
	int i = 0, j = 0;
	while (i < strlen && j < alen) {
		//匹配成功,进行下一步
		if (j == -1 || str[i] == a[j]) {
			i++;
			j++;
		}
		//当不满足匹配时,进行回退,直到匹配成功为止
		else {
			j = next[j];
		}
	}
	//模式匹配成功
	if (j == alen) {
		return i - j + 1;
	}
	//模式匹配失败
	else {
		return -1;
	}
}

补:部分书籍KMP高效匹配可能有些不同,但基本思路都相同,此算法的效率很高,时间复杂度为O(alen + strlen).

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

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

相关文章

无涯教程-JavaScript - NOW函数

描述 NOW函数返回当前日期和时间的序列号。 语法 NOW ()争论 NOW函数语法没有参数。 Notes 如果在输入功能之前单元格格式为"常规",则Excel会更改单元格格式,使其与您的区域设置的日期和时间格式匹配。您可以使用功能区"主页"options卡"数字&quo…

Java学习笔记——34多线程01

多线程 实现多线程进程和线程的区别多线程的实现方式方式一&#xff1a;继承Thread类设置线程名称线程调度线程控制线程生命周期 方式二&#xff1a;实现Runnable接口 实现多线程 进程和线程的区别 进程&#xff1a;是正在运行的程序 是系统进行资源分配和调用的独立单位每一…

文章预览 安防监控/视频存储/视频汇聚平台EasyCVR播放优化小tips

视频云存储/安防监控EasyCVR视频汇聚平台基于云边端智能协同&#xff0c;可实现视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、H.265自动转码H.264、平台级联等。为了便于用户二次开发、调用与集成&#xff0c;…

IG 自动回复:提供无间断客户互动体验

图片来源于&#xff1a;SaleSmartly官网 2023&#xff0c;Instagram拥有将近13亿的月活跃用户&#xff0c;在香港拥有超过400万活跃用户。 Instagram 以图片、长短影片、直播等高互动性的互动方式&#xff0c;吸引了广大的年轻族群&#xff0c;34岁以下的用户即占比了将近全球整…

Day55|动态规划part16:583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

583. 两个字符串的删除操作 leetcode链接&#xff1a;力扣题目链接 视频链接&#xff1a;&#xff1a;LeetCode&#xff1a;583.两个字符串的删除操 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。每步 可以删除任意一个字符串中的…

两个路由器如何连接设置的方法攻略

一、前言 随着智能家居时代来临&#xff0c;家里的网络部署需求开始复杂起来。往往一个路由器已经不能满足需求或者不利于拓展。两个路由器连接最常见的情况是家中已有一个路由器&#xff0c;并且已经通过这个路由器来正常上网。现在是因某些原因想在不改变已经在用的路由器的设…

mysql 字段用了关键字, 无法插入更新数据

1. 表字段用了关键字 explain 2. sql语句中用包裹住关键字 (注意不是单引号) <if test"explain ! null">explain,</if>

CRMEB多端多语言系统文件上传0Day代审历程

Git仓库&#xff1a; https://github.com/crmeb/CRMEB简介&#xff1a; 两天攻防中&#xff0c;某政局子公司官网后台采用的CRMEB开源商城CMS&#xff0c;挺奇葩&#xff0c;别问怎么总让我碰到这种东西&#xff0c;我也不知道&#xff0c;主打的就是一个魔幻、抽象。最后通过…

基于环形队列的生产消费模型

目录 一、信号量 1.提出问题 2.信号量的概念 3.信号量的基本操作 &#xff08;1&#xff09;PV操作 &#xff08;2&#xff09;信号量的使用 二、基于环形队列的生产消费模型 1.环形队列 &#xff08;1&#xff09;复习 &#xff08;2&#xff09;现象 &#xff08;…

酷雷曼第二期无人机技能培训圆满举办

第2期无人机技能培训 2023年8月24日-8月25日&#xff0c;第二期酷雷曼无人机技能培训及执照考试在北京圆满举办&#xff0c;来自五湖四海、全国各地的合作商千里相聚&#xff0c;培训现场热闹融洽&#xff0c;再续精彩盛况。 随着《无人驾驶航空器飞行管理暂行条例》正式发布…

Mysql中group by 使用中发现的问题

当使用 MySQL 的 GROUP BY 语句时&#xff0c;根据指定的列对结果进行分组。在 GROUP BY 分组时&#xff0c;如果某个字段在分组中有多个不同的值&#xff0c;那么就会出现你提到的该字段一直在变化的情况。 这种情况通常是由于在 GROUP BY 中选择的字段与其他非聚合字段不兼容…

【链表OJ 11】复制带随机指针的链表

前言: &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨刷题专栏:http://t.csdn.cn/UlvTc ⛳⛳本篇内容:力扣上链表OJ题目 目录 leetcode138. 复制带随机指针的链表 1. 问题描述 2.代码思路: 2.1拷贝节点插入到…

操作系统强化认识之Shell编程学习与总结

目录 1.Shell的概述 2.Shell脚本入门 3.变量 3.1.系统预定义变量 3.2.自定义变量 3.3.特殊变量 4.运算符 5.条件判断 6.流程控制 6.1.if判断 6.2.case语句 6.3.for循环 6.4.while循环 7.read读取控制台输入 8.函数 8.1.系统函数 8.2.自定义函数 9.正则表示式入…

React原理 - React New Feature

目录 扩展学习资料 React Fragments/Portals/StrictMode【糖果】 Fragments【并列元素外包裹一个伪元素】 Portals【改变组件挂载节点】 Strict Mode【严格模式&#xff0c;老工程中使用&#xff0c;提示即将失效方法】 React Concurrent Mode【大招】 不可阻断渲染/可中…

【广州华锐互动】煤矿设备AR远程巡检系统实现对井下作业的远程监控和管理

煤矿井下作业环境复杂&#xff0c;安全隐患较多。传统的巡检方式存在诸多弊端&#xff0c;如巡检人员难以全面了解井下情况&#xff0c;巡检效率低下&#xff0c;安全隐患难以及时发现和整改等。为了解决这些问题&#xff0c;提高煤矿安全生产水平&#xff0c;越来越多的企业开…

C#winform自定义软键盘

软键盘应用 触摸一体机没有硬件键盘&#xff0c;系统软键盘占面积大&#xff0c;位于屏幕底部&#xff0c;点击不是很方便。某些时候只需要输入数字&#xff0c;这时弹出九宫格数字键盘就足够了。 以下实现的是弹出一个弹窗作为软键盘。 实现 创建一个窗体FrmSoftKey&#xf…

【Git-Exception】Git报错:fatal: unable to auto-detect email address

报错信息&#xff1a; *** Please tell me who you are. Run git config --global user.email “youexample.com” git config –global user.name “Your Name” to set your account’s default identity. Omit --global to set the identity only in this repository. fatal…

JVM:JIT实时编译器

一、相关 ⾼级编程语⾔按照程序的执⾏⽅式分为两种 编译型&#xff1a;一次性将代码编译为机器码解释型&#xff1a;通过解释器一句一句的将代码解释为机器码之后&#xff0c;再运行。每个语句都是执行的时候才翻译。 JAVA代码执行过程 &#xff08;编译阶段&#xff09;首先将…

SAP 物料主数据屏幕增强

增强步骤 1.为主表添加一个附加结构 根据业务需求新建一个结构&#xff0c;结构中放入需要增强的屏幕字段并激活。 打开事务代码SE11&#xff0c;在需要保存的主表中添加这个附加结构并激活。 注&#xff1a;根据业务需求及屏幕增强的视图判断需要保存的主表是哪张&#xff…

AutoSar Com模块

文章目录 Com模块功能通信传输控制整体 communication 结构Signal 发送流程设置信号的 UpdateBit信号的超时处理信号的传输方式 Signal 发送时序图Signal 接收流程接收信号的 UpdateBit Signal 接收时序图Com_TxPduInfo / Com_RxPduInfo、Com_PduGrpVector 数据来源Com_TxSigGr…