数据结构--KMP算法

数据结构–KMP算法

首先我在这里提出以下问题,一会一起进行探讨

1.什么是最长公共前后缀
2. KMP算法怎么实现对匹配原理
3. 最长公共前后缀怎么求解

KMP算法可以用来解决什么问题?
答:在字符串中匹配子串,也称为模式匹配

分析

什么是最长公共前后缀?

通俗来说,就是一个字符串开头到某一个位置与其某一个位置到字符串结束一模一样,即 P0…PK-1 与 Pi-k…Pi-1的字符串相同,注意我们这里的最长公共前后缀是指的真串,即不包含该字母,如对于字符串 aba,其前缀有 a,ab,其后缀有ba,a那么最长公共公共前后缀为a
下面是实例:
对于ababcabababe
我们手动遍历一次从 i = 0开始
i = 0,字符串为 a
因为不包含本身,所以其无前后缀,那么自然也没有公共前后缀

i = 1,字符串为 ab
其 前缀为 a,后缀为 b,无公共前后缀

i = 2,字符串为 aba
其 前缀有 a,ab 后缀有 ba,a 公共前后缀为a

i = 3,字符串为 abab
其前缀为 a,ab,aba 其后缀有bab,ab,b最长公共前后缀为ab

i = 4,字符串为 ababc
其前缀为 a,ab,aba,abab 其后缀有babc,abc,bc,c 所以无公共前后缀

同理,下面的我们肉眼观察(开头有没有一段字符串和结尾一段字符串相同)

i = 5,字符串为 ababca
其最长公共前后缀为 a

i = 6,字符串为 ababcab
其最长公共前后缀为 ab

i = 7,字符串为 ababcaba
其最长公共前后缀为 aba

i = 8,字符串为 ababcabab
其最长公共前后缀为 abab

i = 9,字符串为 ababcababa
其最长公共前后缀为 aba

i = 10,字符串为 ababcababab
其最长公共前后缀为 abab

i = 11,字符串为 ababcabababe
其无公共前后缀

对于 i 遍历到每个元素,我们可以创建一个Next[ ]数组来保存该元素之前的所有字符形成的字符串的最长公共前后缀

那么对于任意字符串,第一个元素没有前面的元素,我们则把其的Next置位-1,即Next[ 0 ] = -1;而对于第一个元素,我们知道只有一个元素时,其永远没有不包含本身的前后缀,所以第二个元素保存的该元素之前的所有字符形成的字符串的最长公共前后缀永远为0,即永远Next[ 1 ] = 0;
对于这样保存的方法,我们有下图
在这里插入图片描述
那么问题是怎么求解Next[ ] 数组

Next[ ]数组求解(最长公共前后缀怎么求解)

完成从上面的理论分析到代码实现,我们需要两个"指针",因为最长公共前后缀本质上前面的一段字符串等于最后的一段字符串,那么,我们用 i 来完成对后面字符串的遍历,而 用 k 来完成对前面字符串的遍历(看不懂别急,下面还有解释)
代码:

public void getNext(int [] Next,String s){int i = 0;// 遍历字符串的后端int k = -1;// 遍历字符串的前端Next[0] = -1;// 初始第一个为-1while (i < s.length()){if (k == -1 || s.charAt(i) == s.charAt(k)){// 如果前面没有公共前后缀时,k为-1,那么其下一个索引元素储存的就为++k(就为0)// 如果前面的字符串有最长公共前后缀,且在该元素(后面字符串的最后一位)等于前面字符串(存储的前面字符串的公共前缀)的下一位时// 那么下一个索引元素(++i)储存的就为++kNext[++i] = ++k;}else {// 如果该元素(后面字符串的最后一位)不等于前面字符串(存储的前面字符串的公共前缀)的下一位// 令 k = Next[k]得到其前面的字符串的公共前缀的下一位(不懂可以看图)k = Next[k];}}}

对于字符串ababcabababe
这里举几个特殊的例子来进行原理说明:
i 为遍历后缀的索引,k为遍历前缀的索引
这里约定:i 指向的位置为黄色,k指向的位置为绿色

1.当该元素的前面的字符串具有公共前后缀时,当这个元素和前面字符串的公共前缀的下一位相等,那么就会形成在原来长度基础上+1的新的最长公共前后缀
当字符串遍历到b时,此时字符串为ababcabab
在这里插入图片描述

如上图,此时在对k = 3(绿色),i = 8(黄色)位置进行判断,此时完成上面最后蓝色位置的判断后,黄色b应该保存前面字符串的最长的公共前后缀3,然后此时i 指向黄色位置,k指向绿色位置,我们发现只要黄色和绿色位置的元素相等,他们就可以在前面的基础上形成一个新的最长公共前后缀,长度加1,为4,存储在如图橘色位置,如此 那么如果
s.charAt(i) == s.charAt(k)
且其前面的字符串有公共前后缀,则下个元素存储的Next数组中的值会在前面的值的基础上加1
Next[++i] = ++k;

2.当这个元素和前面字符串的公共前缀的下一位不相等时
我们接着上面的情况继续遍历下去,上面判断完i(黄),k(绿)色的字符后,i 增加到下图黄色位置,k增加到下图绿色位置,并把长度4(如图所示的蓝色公共前后缀)存储在其Next[ ]数组里,此时k = 4,i = 9 ,字符串为ababcababa
此时判断在 k = 4 和 i = 9 的位置的字符是否相等,不相等的话我们令 k = Next[ k ];
在这里插入图片描述
k = Next[k];
然后重复的判断,k = Next[ k ] 时 与 i = 9 时的字符是否相等
原理解释,因为上图的绿色与黄色是对应关系,在他们之前的字符串,上图蓝色是相同的,而我此时读取上图绿色位置的Next数组的值,就可以知道上图绿色前面的字符串有几位字符串长度的公共前后缀,在这个例子当中我们可以知道是两个,即下图的蓝色和紫色是相同的,因为绿色和黄色位置前面字符串是相同的,所以黄色前的字符串也有类似的性质
那么我们知道绿色前面的字符串的蓝色与紫色相等,而黄色前面的字符串和绿色前面的字符串相同,且其蓝色也等于紫色,那么 蓝1(第一部分蓝色) = 紫1(第一部分紫色),紫1 = 紫2(第二部分紫色),可知 蓝1 = 紫2,这样我们就直接知道了其除去上图蓝色外的最长的公共前后缀
在这里插入图片描述
在这个基础上我们只用完成下图 k = 2(绿) 和 i = 9(黄)的位置的字符判断,而减少判断其前面的蓝色部分的字符串部分,如果k = 2(绿) 和 i = 9(黄)的位置的字符不相等的话,重复上述操作,k = Next[ k ],得k = Next[ 2 ] = 0,然后重复上面的操作,最后把最长公共前后缀的长度存储在下图橘色位置
在这里插入图片描述

KMP算法怎么实现对匹配原理

我们仍然举例子来介绍这种匹配方式,如下有:
主串S:ababcabcacbab,模式串T:abcac
传统的BF解法是 在主串 ababcabcacbab 的每一个元素开始把子串匹配,直到匹配成功,这种匹配方式需要 把 主串的 指针 i 回溯
BF 代码

int BF(char S[],char T[])
{int i=0,j=0;while(S[i]!='\0'&&T[j]!='\0'){if(S[i]==T[j]){i++;j++;}else{i=i-j+1;j=0;}}if(T[j]=='\0') return (i-j);     //主串中存在该模式返回下标号 else return -1;     //主串中不存在该模式 
}

BF的流程
约定:i绿色指向主串,k黄色指向子串
第一次匹配(从 i = 0 开始)
在这里插入图片描述
匹配到 i = 2 和 j = 2 时发现不匹配,i 退回到 i = 1 ,从 i = 1 ,j = 0开始重新匹配
在这里插入图片描述
第三次匹配(从 i = 2 开始匹配)
发现 i = 6 和 j = 4 不匹配,蓝色是起始位置,下次从 i = 3,j = 0 开始匹配
在这里插入图片描述
上面就是BF算法的实现,我们发现每次匹配失败后,i都要回退,这样需要消耗大量时间,而如果我们可以读取子串该匹配元素的前面字符串的最长公共前缀(橘色),那么看图一,图中蓝色位置的字符串相等,而根据其公共前后缀相等,看图二,其中蓝色部分相等,那么我们的i就可以不回退,而令j = 该位置Next[ ]数组存储的元素,再进行判断,看图三,我们知道此时i 仍然等于 6,j = 1,此时进行遍历
而其前面字符串如果没有公共前缀,那么j = 0,就是从子串头开始遍历

图一:
在这里插入图片描述
图二:

在这里插入图片描述
图三:
在这里插入图片描述

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

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

相关文章

mac电脑安装软件报错:无法检查更新,请检查你的互联网连接

1、点菜单栏搜索图标&#xff0c;输入&#xff1a;终端 &#xff0c;找到后&#xff0c;点击打开 2、输入以下命令&#xff1a;&#xff08;复制粘贴进去&#xff09;回车安装 /usr/sbin/softwareupdate --install-rosetta --agree-to-license 3、提示【Install of Rosetta …

电商技术揭秘十八:电商平台的云计算与大数据应用小结

电商技术揭秘相关系列文章 电商技术揭秘一&#xff1a;电商架构设计与核心技术 电商技术揭秘二&#xff1a;电商平台推荐系统的实现与优化 电商技术揭秘三&#xff1a;电商平台的支付与结算系统 电商技术揭秘四&#xff1a;电商平台的物流管理系统 电商技术揭秘五&#xf…

spring boot 集成 flyway依赖 做数据库迁移,让部署没烦恼

flyway 是一个敏捷工具&#xff0c;用于数据库的移植。采用 Java 开发&#xff0c;支持所有兼容 JDBC 的数据库。 主要用于在你的应用版本不断升级的同时&#xff0c;升级你的数据库结构和里面的数据。 还是直接上代码 第一步&#xff1a; <!-- Flyway 数据库迁移 依赖 他…

MySQL排序原理与优化方法(9/16)

order by排序优化 MySQL排序策略 内存临时表 or 磁盘临时表&#xff1f; **内存临时表排序&#xff1a;**在MySQL中&#xff0c;使用InnoDB引擎执行排序操作时&#xff0c;当处理的数据量较小&#xff0c;可以在内存中完成排序时&#xff0c;MySQL会优先使用内存进行排序操作…

知名的开源大模型及其特点

目前&#xff0c;开源的大模型领域涌现出了许多具有不同特点和优势的模型。这些开源大模型不仅推动了AI技术的发展&#xff0c;也为研究者和开发者提供了丰富的资源和工具&#xff0c;促进了AI应用的创新和多样化。以下是一些知名的开源大模型及其特点。北京木奇移动技术有限公…

Python测试框架之pytest详解

前言 Python测试框架之前一直用的是unittestHTMLTestRunner&#xff0c;听到有人说pytest很好用&#xff0c;所以这段时间就看了看pytest文档&#xff0c;在这里做个记录。 官方文档介绍&#xff1a; Pytest is a framework that makes building simple and scalable tests e…

2024年ERP软件上中下游结构分析及细分行业研究

环洋咨询Global Info Research的ERP软件市场调研报告提供ERP软件市场的基本概况&#xff0c;包括定义&#xff0c;分类&#xff0c;应用和产业链结构&#xff0c;同时还讨论发展政策和计划以及制造流程和成本结构&#xff0c;分析ERP软件市场的发展现状与未来市场趋势&#xff…

String类(1)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

三年Android开发经验面试经历分享

最近&#xff0c;参加了多家公司的面试&#xff0c;下面是我所经历的一些面试问题及自己的回答思路。 一、京东面试 一面&#xff1a; 项目内容&#xff1a;主要讲述了在实习期间参与的项目&#xff0c;以及在项目中负责的工作和取得的成果。MVP模式&#xff1a;解释了MVP模…

CSS实现三栏自适应布局(两边固定,中间自适应)

绝对定位的元素会脱离文档流&#xff0c;它们是相对于包含块&#xff08;通常是最近的具有相对定位、绝对定位或固定定位属性的父元素&#xff09;进行定位的。当你把一个绝对定位的元素的高度设置为100%时&#xff0c;它会相对于其包含块的高度来确定自己的高度。如果包含块是…

政安晨:【深度学习神经网络基础】(六)—— 前馈神经网络

目录 简述 前馈神经网络结构 计算输出 初始化权重 径向基函数神经网络 径向基函数 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎…

Centos7源码方式安装Elasticsearch 7.10.2单机版

版本选择参考&#xff1a;Elasticsearch如何选择版本-CSDN博客 下载 任选一种方式下载 官网7.10.2版本下载地址&#xff1a; https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.2-linux-x86_64.tar.gz 网盘下载链接 链接&#xff1a;https://pan…

OpenGL Assimp 加载3D模型介绍

OpenGL Assimp 加载3D模型介绍 Assimp对应模型结构体解说 所有的模型、场景数据都包含在scene对象中&#xff0c;如所有的材质和Mesh。同样&#xff0c;场景的根节点引用也包含在这个scene对象中 场景的Root node&#xff08;根节点&#xff09;可能也会包含很多子节点和一个…

c++的学习之路:16、list(3)

上章有一些东西当时没学到&#xff0c;这里学到了将在补充&#xff0c;文章末附上代码&#xff0c;思维导图。 目录 一、赋值重载 二、带模板的创建 三、析构函数 四、代码 五、思维导图 一、赋值重载 这里的赋值重载就是直接利用交换函数进行把传参生成的临时数据和需要…

对称加密学习

对称加密是一种加密技术&#xff0c;它使用相同的密钥进行数据的加密和解密操作。这种加密方法因其高效性和速度优势&#xff0c;在数据加密领域得到了广泛的应用。 下面是两篇文章&#xff1a; AES加密学习-CSDN博客 加密算法学习-CSDN博客 推荐关注加密专栏&#xff1a; …

建模实例评点(6)业务流程-农业大棚

1 00:00:02,650 --> 00:00:06,000 假设这一步不是老司机来做 2 00:00:06,320 --> 00:00:08,430 主管不是老司机&#xff0c;是个小白 3 00:00:08,440 --> 00:00:09,470 比如像我这样 4 00:00:09,990 --> 00:00:11,580 潘加宇去做这个事情 5 00:00:12,460 -->…

C++感受4-HelloWorld中文版——认识编码

及时了解“编码”对编写代码的影响&#xff0c;是中国程序员越早知道越好的知识点。 一分钟了解什么叫“编码”和“解码”&#xff1b;通过实际演示&#xff0c;充分理解中文Windows下&#xff0c;C源代码编码需要注意的地方&#xff1b;通过 -finput-charsetutf8 等 g 编译配置…

如何训练自己的ChatGPT?需要多少训练数据?

近年&#xff0c;聊天机器人已经是很常见的AI技术。小度、siri、以及越来越广泛的机器人客服&#xff0c;都是聊天机器人的重要适用领域。然而今年&#xff0c;ChatGPT的面世让这一切都进行到一个全新的高度&#xff0c;也掀起了大语言模型&#xff08;LLM&#xff09;的热潮。…

麒麟系统ARM安装rabbitmq

简单记录下&#xff0c;信创服务器&#xff1a;麒麟系统&#xff0c;安装rabbitmq的踩坑记录。 本文章参考了很多大佬文章&#xff0c;我整理后提供。 一、安装基础依赖 yum -y install make gcc gcc-c kernel-devel m4 ncurses-devel openssl-devel unixODBC-devel 二、下载…