【算法篇】KMP算法,一种高效的字符串匹配算法

我们今天了解一个字符串匹配算法-KMP算法,内容难度相对来说较高,建议先收藏再细品!!!
在这里插入图片描述

KMP算法的基本概念

KMP算法是一种高效的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。

该算法的主要使用场景就是在字符串(也叫主串)中的模式串(也叫字串)定位问题,常见的有“求子串出现的起始位置”、“求子串的出现次数”等。

解决什么问题

假设有两个字符串,分别为文本串和模式串,如下:


求在文本串中是否出现过上面的模式串。

暴力解法

当出现不匹配的字符时,暴力算法会进行如下两个操作:

  • 向后移动模式串
  • 目标串和模式串的指针都回溯

KMP优化解法

使用暴力算法的时间复杂度较高,如何去优化呢?

优化方向:防止或减少主串指针回溯

当出现不匹配的字符时,目标串指针不动,只移动模式串。

移动前,指针左边的字符已经匹配了,所以要让移动后的目标串的指针不会苏,需要保证:模式串移动之后,在指针左边的字符也是匹配的。

  • 找相同字符必须是从模式串第一个位置开始
  • 模式串移动方式由能找到的最长的相同字符决定,如果不是最长的,可能会漏掉能匹配的内容。
  • 找到的最长的相同字符串长度必须小于已经匹配的内容长度,前后部分可以有交叉内容

KMP算法小结

  • 发生不匹配时,指针所指的下标等于已经匹配的长度
  • 发生不匹配时,需要移动的长度 = 已经匹配的长度 - 前后相同的最大长度
  • 前后相同的最大长度为空的地方用-1补齐

KMP算法中的next数组

当目前的C和A不匹配时,由于A的前面也全都是A,所以前面也一定不匹配,对于这个模式串,可以直接将指针移动到-1的位置。

所以需要再对next数组进行改进,改进后的数组我们命名为nextval。

优化next数组

总结:若str[j] == str[next[j]],那么nextval[j] = nextval[next],否则nextval[j] = next[j]

判断是否匹配

先给定两个字符串,分别表示文本串和模式串,通过kmp(稍后写这个函数)进行比较,找到第一次出现模式串的位置,如果没有匹配上则给出提示。

char *text = "aaaaaabaaa",*pattern = "aaaab";
int index = kmp(text,pattern);
if(index == -1)
{cout << "没有匹配上内容";
} 
else{cout << "匹配上了,起始位置为:" << index;
}

输出next数组

next指针用来动态获取模式串的长度

int kmp(char *text,char *pattern){int index = -1;int txt_len = strlen(text),ptn_len = strlen(pattern);int *next = (int *)malloc(sizeof(int) * ptn_len);get_next(pattern,next,ptn_len);free(next);return index;
}

计算next数组

若str[j] == str[k]时,next[j+1] = k+1
若str[j] != str[k]时,k = next[k]

void get_next(char *str,int *next,int len){int j = 0,k = -1;next[0] = -1;while(j < len-1){if(k == -1 || str[j] == str[k]){k++;j++;next[j] = k;}else k = next[k];} 
}

遍历输出next数组

从下标为0的位置到ptn_len依次输出next数组内的元素

int kmp(char *text,char *pattern)
{int index = -1;int txt_len = strlen(text),ptn_len = strlen(pattern);int *next = (int *)malloc(sizeof(int) * ptn_len);get_next(pattern,next,ptn_len);for(int i=0;i<ptn_len;i++){printf("%d ",next[i]);}free(next);return index;
}

输出nextval数组

将next数组变为nextval数组(此处的next数组实际上是nextval数组)

if(k == -1 || str[j] == str[k]){k++;j++;if(str[j] == str[k]){next[j] = next[k];}else{next[j] = k;}
}
else{k = next[k];
} 

输出匹配位置

int index = -1,txt_idx = 0,ptn_idx = 0;
... ...
get_next(pattern,next,ptn_len);while((txt_idx < txt_len) && (ptn_idx < ptn_len))
{if(text[txt_idx] == pattern[ptn_idx] || ptn_idx == -1){txt_idx++;ptn_idx++;}else{ptn_idx = next[ptn_idx];}
}if(ptn_idx >= ptn_len){index = txt_idx - ptn_len;
}

利用KMP算法解决字符串匹配问题,能极大节约时间复杂度。关于KMP算法还有什么问题的话,欢迎各位留言交流~

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

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

相关文章

LLMs之gptpdf:gptpdf的简介、安装和使用方法、案例应用之详细攻略

LLMs之gptpdf&#xff1a;gptpdf的简介、安装和使用方法、案例应用之详细攻略 目录 gptpdf的简介 1、处理流程 第一步&#xff0c;使用 PyMuPDF 库&#xff0c;对 PDF 进行解析出所有非文本区域&#xff0c;并做好标记&#xff0c;比如: 第二步&#xff0c;使用视觉大模型&…

离婚后,孩子就读私立高中的高昂学费谁承担?

江苏省南京市六合区人民法院审结一起抚养费纠纷案件&#xff0c;认定夫妻双方在决定孩子教育事务上均存在责任&#xff0c;为保障临近高考的未成年子女的切身利益&#xff0c;认定由夫妻双方按比例承担教育费。   2015年6月&#xff0c;李某与王某离婚&#xff0c;双方之子小…

PCL 有序点云的法线估计(使用积分图进行法线估计)

使用积分图进行法线估计 一、概述1.1 概念1.2 有序点云与无序点云1.2.1 有序点云1.2.2 无序点云1.3 代码讲解二、代码实现三、结果示例一、概述 1.1 概念 使用积分图进行法线估计:计算一个有序点云的法线,注意该方法只适用于有序点云。 1.2 有序点云与无序点云 有序点云与无…

MySQL安装时initializing database失败

问题页面&#xff1a; 解决方法&#xff1a; 1.勾选红框中的选项&#xff1a; 2.将下图红框中全部改为英文&#xff1a; 然后一路next就可以了。

cs231n作业1——KNN

参考文章&#xff1a;assignment1——KNN KNN 测试时分别计算测试样本和训练集中的每个样本的距离&#xff0c;然后选取距离最近的k个样本的标签信息来进行分类。 方法1&#xff1a;Two Loops for i in range(num_test):for j in range(num_train):dist X[i, :] - self.X…

vue3使用方式汇总

1、引入iconfont阿里图库图标&#xff1a; 1.1 进入阿里图标网站&#xff1a; iconfont阿里&#xff1a;https://www.iconfont.cn/ 1.2 添加图标&#xff1a; 1.3 下载代码&#xff1a; 1.4 在vue3中配置代码&#xff1a; 将其代码复制到src/assets/fonts/目录下&#xff1…

Mysql之Using index for skip scan

一、Using index for skip scan 在 MySQL 中&#xff0c;EXPLAIN 语句用于显示查询执行计划&#xff0c;帮助我们理解查询是如何被执行的&#xff0c;以及如何优化查询。其中&#xff0c;Extra 列提供了关于查询执行的一些额外信息。当 Extra 列显示 Using index for skip sca…

CF F. Alex‘s whims

原题链接&#xff1a;Problem - 1899F - Codeforces 题目大意&#xff1a;要求构建出一颗树&#xff0c;多次询问树的叶节点之间的距离有没有达到要求的距离&#xff0c;如果有直接输出-1 -1 -1&#xff0c;如果没有可以断开一条边和连上一条边&#xff0c;输出x y z&#xff…

mp4视频太大怎么压缩不影响画质,mp4文件太大怎么变小且清晰度高

在数字化时代&#xff0c;我们常常面临视频文件过大的问题。尤其是mp4格式的视频&#xff0c;文件大小往往令人望而却步。那么&#xff0c;如何在不影响画质的前提下&#xff0c;有效地压缩mp4视频呢&#xff1f;本文将为您揭秘几种简单实用的压缩技巧。 在分享和存储视频时&am…

Open3D 计算点云的欧式距离

目录 一、概述 1.1欧式距离定义 1.2作用和用途 二、代码实现 2.1关键函数 2.2完整代码 三、实现效果 3.1原始点云 3.2处理后点云 一、概述 在Open3D中&#xff0c;compute_point_cloud_distance函数用于计算两个点云之间的距离。具体来说&#xff0c;它计算的是源点云…

【计算机网络仿真】b站湖科大教书匠思科Packet Tracer——实验16 路由信息协议RIP

一、实验目的 1.验证RIP协议的作用&#xff1b; 二、实验要求 1.使用Cisco Packet Tracer仿真平台&#xff1b; 2.观看B站湖科大教书匠仿真实验视频&#xff0c;完成对应实验。 三、实验内容 1.构建网络拓扑&#xff1b; 2.验证RIP协议。 四、实验步骤 1.构建网络拓扑 …

sdbusplus:将文件描述符作为method的返回值

sdbusplus:通过文件描述符作为参数调用method_libsdbusplus-CSDN博客 介绍了使用文件描述符作为参数的方式 文件描述符也可以作为method的返回值,然后用来传递数据 服务器端: //s.cpp #include <sdbusplus/asio/connection.hpp> #include <sdbusplus/asio/object…

js list to tree

在JavaScript中&#xff0c;将列表转换为树结构是一种常见的操作&#xff0c;尤其是在处理需要层级展示的数据&#xff0c;如菜单、分类等。这通常涉及到递归函数和对象的引用。以下是一个简单的例子&#xff0c;展示了如何将一个扁平化的列表转换为多层级树结构。 假设我们有以…

【图像处理】Krita 一款开源免费专业图像处理软件分享

软件介绍 Krita 是一款专业级的图像处理软件&#xff0c;适合数字绘画和创作。它不仅支持栅格图像的细致编辑&#xff0c;还提供了强大的矢量图形工具&#xff0c;使得用户可以在同一个平台上完成多种类型的创作工作。同时具备一定的矢量图形编辑功能。Krita 的首要用途是绘画…

黑马点评商户缓存查询作业——Redis中查询商户类型

记录下自己在gpt帮助下完成的第一个需求~~~ 1. ShopTypeController 2. IShopTypeService 3. ShopTypeServiceImpl&#xff08;模仿ShopServiceImpl来写的&#xff09; 一共分为“1.redis中查询缓存”→“2.判断缓存是否存在&#xff0c;存在直接返回”→“3.缓存不存在则去查数…

2-28 基于matlab提取出频域和时域信号的29个特征

基于matlab提取出频域和时域信号的29个特征&#xff0c;主运行文件feature_extraction&#xff0c;fre_statistical_compute和time_statistical_compute分别提取频域和时域的特征&#xff0c;生成的29个特征保存在生成的feature矩阵中。程序已调通&#xff0c;可直接运行。 2-2…

C语言 printf 函数多种输出格式以及占位输出

一、输出格式 在C语言中&#xff0c;printf 函数提供了多种输出格式&#xff0c;用于控制不同类型数据的输出方式。 1.整数输出格式 %d&#xff1a;以十进制形式输出整数。 %o&#xff1a;以八进制形式输出整数&#xff08;无前导0&#xff09;。 %x 或 %X&#xff1a;以十六进…

JavaScript里方括号[]的使用

我们知道可用方括号来表示数组或者JSON对象的属性值&#xff0c;其实在特定场合&#xff0c;方括号还有妙用的。 比如我有数据源是一组JSON&#xff0c;其中有一个属性是时间字符串&#xff0c;我想对时间的小时、星期、日、月分别进行处理。每条JSON都各自生成一条新的JSON&am…

代码随想三刷动态规划篇9

代码随想三刷动态规划篇9 714. 买卖股票的最佳时机含手续费题目代码 714. 买卖股票的最佳时机含手续费 题目 链接 代码 class Solution {public int maxProfit(int[] prices, int fee) {//卖的时候-feeif(prices.length1){return 0;}int[][] dp new int[prices.length][2]…

EAI四个层次服务-系统架构师(二十六)

1、&#xff08;重点&#xff09;系统应用集成提供了4个不同层次服务&#xff0c;最上层服务是&#xff08;&#xff09;服务。 解析: EAI&#xff08;Enterprise Application Integration&#xff09;系统应用集成&#xff0c;相关概念。 实施EAI必须保证&#xff1a;应用程…