KMP-子串匹配算法-关键点理解

1.理解next[]数组的使用与来历

2.求解next[]数组

一、kmp算法的原理

        首先观察暴力解法:假设主串为:abdxxabc,模式串为abxxabd。

暴力解法,就是对主串每个字符作为第一个字符,开始和模式串比较。

比如:从主串第一个字符a开始,比较到d发现不相等,然后从第二个字符b开始,直接不相等。以此类推,直到匹配或者到主串末尾。

           abxabc|abxabd                       ​​​​​​​abxabc|abxabd     ...       abxabc|abxabd

           abxabd                                     abxabd                ...                    abxabd

             图一                                         图二                                       图三

比较操作的时间复杂度为O(m×n)。

kmp算法在此基础上进行改进,关键点为,利用已经比较过的部分,比如图一的abxabd。

        当遇见不匹配的情况时,通过模式串的最长相等前后缀来确定下一次模式串比较的位置,并且不需要回退主串和模式串。前缀为不包含最后一个字符,包含第一个字符的子串,后缀为不包含第一个字符,保护最后一个字符的字串。

        理解:匹配过程中,不匹配的情形只有两种情况,其实也可以看成一种情况。第一种情况:第一个字符就不匹配,也就是说不匹配的字符前面没有字符。如图二。第二种情况:第n个字符不匹配,前n-1个字符匹配。如图一。

       第一种情况由于第一个字符就不匹配,所以主串直接遍历下一个字符,模式串还是第一个字符开始比较。第二种情况:如图一,abxab是匹配的,此时,我们只需要检查abxab这个字符串的最长相等前后缀的长度,最长相等前后缀为ab,长度为2。下一次我们直接比较模式串下标为2的字符x和此时主串不相等的字符c。然后重复上面的比较操作。

        关键点是理解最长相等前后缀的性质。在已经匹配的字符串中,如何最长相等前后缀为0,也即是没有相等的前后缀,那么显然,由于已经匹配的字符串在模式串中为模式串的一个前缀,而在主串中为已经遍历过的匹配的字符串的后缀,假设从i开始比较,到j不相等,主串i ~ j-1这一部分是模式串的一个前缀,因为肯定是从模式串的第一个字符开始比较的。而i - j-1这一部分如果没有相等的前后缀,那么显然不可能有和模式串匹配的部分,因为i~j-1是模式串的一个前缀,你都没有后缀等于前缀,所以主串不用回退,直接遍历下一个字符;如果有相等的前后缀,我们取最长的相等前后缀,i~j-1是模式串的一个前缀,假设最长的相等前后缀长度为2,也就是i, i+1是等于j-2, j-1,所以模式串的下一次比较的位置就是i+2,因为i~j-1也是主串的一部分,主串下一次比较的开始字符是j。

2.关键的最长相等前后缀的求解,也就是常说的next的数组。也就是前缀表。

一、暴力求解:两个指针,left,right,分别指向后缀的开始,前缀的末尾。从最长的前后缀字串开始比较,逐渐缩短,直到不相等。

二、常用解法:kmp的思路,其实求解next数组的过程中也用到了kmp的算法思想。一个指针j,表示以i-1为尾部的前缀字符串的最长相等前后缀的长度,也即是j指向最长相等前缀的下一个字符。i遍历字符串,从0开始。显然,第一个前缀,最长相等前后缀长度为0。

比如字符串abcxabxabcxx。next[]数组:next[0]:前缀a的最长相等前后缀的长度;next[1]:前缀ab的最长相等前后缀的长度;next[2]:前缀abc的最长相等前后缀的长度,....表示以i结尾的前缀字符串的最长相等前后缀的长度。

for(i = 0; i < str.size(); ++i)遍历一个一个求next[i]数组。

if (str[i] == str[j])   next[i] = ++j;

abcxabxabcxx: 假设此时i遍历到了x,j为i-1结尾的前缀字符串的最长相等前后缀长度,也就是红色部分表示的前缀字符串的最长相等前后缀长度,为2,也即是j指向最长相等前缀的下一个字符c。

其实就是next[i]是和next[i-1]有关系的。

关键是str[i] != str[j], while(j > 0 && str[i] != str[j]) j = next[j-1];其实就是把字符串0~j看成模式串,

i-j~i看成主串,因为指针j,表示以i-1为尾部的前缀字符串的最长相等前后缀的长度,也即是j指向最长相等前缀的下一个字符。i-j~i-1是等于0-j-1的。

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

参考代码:

class Solution {
public:int strStr(string haystack, string needle) {//第一部分:求解next[]数组vector<int> next(needle.size());int j = 0;for(int i = 1; i < needle.size(); ++i){while(j > 0 && needle[j] != needle[i]){j = next[j - 1];}if(needle[i] == needle[j]){j++;}next[i] = j;}//第二部分:匹配文本串j = 0;for(int i = 0; i < haystack.size(); ++i){while(j > 0 && needle[j] != haystack[i])j = next[j - 1];if(haystack[i] == needle[j]){j++;}if(j == needle.size())return i - j + 1;}return -1;}
};

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

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

相关文章

Linux中的selinux,磁盘管理

一、selinux 作用&#xff1a;通过对软件进程限制某些权限&#xff0c;从而保证系统的安全。通过上下文类型和设定好的上下文类型是否一致。如果一致&#xff0c;那么软件就可以完成后续的操作&#xff0c;例如访问文件中数据&#xff0c;或者让数据通过某个端口。做好个人防护…

Linux应用:Linux的信号

什么是信号 信号是一种软件中断&#xff0c;用于通知进程系统中发生了某种特定事件。它是操作系统与进程之间&#xff0c;以及进程与进程之间进行异步通信的一种方式。在 Linux 系统中&#xff0c;信号是一种比较简单的进程间通信机制。当一个信号产生时&#xff0c;内核会通过…

Linux笔记之Ubuntu22.04安装IBus中文输入法教程

Linux笔记之Ubuntu22.04安装IBus中文输入法教程 code review&#xff01; 文章目录 Linux笔记之Ubuntu22.04安装IBus中文输入法教程安装 IBus 并配置中文输入法步骤 1: 安装 IBus 和拼音插件步骤 2: 设置 IBus 为默认输入法框架步骤 3: 重启会话步骤 4: 添加中文输入法步骤 5: …

【AIGC前沿】MiniMax海螺AI视频——图片/文本生成高质量视频

目录 1.MiniMax海螺AI视频简介 2.使用教程 1.MiniMax海螺AI视频简介 海螺视频&#xff0c;作为 MiniMax 旗下海螺 AI 平台精心打造的 AI 视频生成工具&#xff0c;致力于助力用户产出高品质视频内容。该工具依托 abab-video-1 模型&#xff0c;具备强大的文生视频功能。用户…

Kubeasz工具快速部署K8Sv1.27版本集群(二进制方式)

文章目录 一、基本信息二、服务器初始化操作三、使用Kubeasz部署K8S集群四、验证集群 一、基本信息 1、部署需要满足前提条件&#xff1a; 注意1&#xff1a;确保各节点时区设置一致、时间同步&#xff1b;注意2&#xff1a;确保在干净的系统上开始安装&#xff1b;注意3&…

在VMware上部署【Ubuntu】

镜像下载 国内各镜像站点均可下载Ubuntu镜像&#xff0c;下面例举清华网站 清华镜像站点&#xff1a;清华大学开源软件镜像站 | Tsinghua Open Source Mirror 具体下载步骤如下&#xff1a; 创建虚拟机 准备&#xff1a;在其他空间大的盘中创建存储虚拟机的目录&#xff0c…

2025年Postman的五大替代工具

虽然Postman是一个广泛使用的API测试工具&#xff0c;但许多用户在使用过程中会遇到各种限制和不便。因此&#xff0c;可能需要探索替代解决方案。本文介绍了10款强大的替代工具&#xff0c;它们能够有效替代Postman&#xff0c;成为你API测试工具箱的一部分。 什么是Postman&…

wow-rag—task5:流式部署

我们希望做一个流式输出的后端&#xff0c;然后让前端去捕获这个流式输出&#xff0c;并且在聊天界面中流式输出。 首先构造流式输出引擎。 # 构造流式输出引擎 query_engine index.as_query_engine(streamingTrue, similarity_top_k3,llmllm)然后生成response_stream&#x…

投资日记_道氏理论技术分析

主要用于我自己参考&#xff0c;我感觉我做事情的时候容易上头&#xff0c;忘掉很多事情。 技术分析有很多方法&#xff0c;但是我个人相信并实践的还是以道氏理论为根本的方法。方法千千万万只有适合自己价值观&#xff0c;习惯&#xff0c;情绪&#xff0c;性格的方法才是好的…

LangChain4j入门指南:Java开发者的AI应用新起点

什么是LangChain和LangChain4j&#xff1f; LangChain是⼀个⼤模型的开发框架&#xff0c;使⽤ LangChain 框架&#xff0c;程序员可以更好的利⽤⼤模型的能⼒&#xff0c;⼤⼤提⾼编 程效率。如果你是⼀个 Java 程序员&#xff0c;那么对 LangChain 最简单直观的理解就是&…

【实测闭坑】LazyGraphRAG利用本地ollama提供Embedding model服务和火山引擎的deepseek API构建本地知识库

LazyGraphRAG 2024年4月&#xff0c;为解决传统RAG在全局性的查询总结任务上表现不佳&#xff0c;微软多部门联合提出Project GraphRAG&#xff08;大模型驱动的KG&#xff09;&#xff1b;2024年7月&#xff0c;微软正式开源GraphRAG项目&#xff0c;引起极大关注&#xff0c…

压力测试实战指南:JMeter 5.x深度解析与QPS/TPS性能优化

一、压力测试基础概念 1.1 什么是压力测试&#xff1f; 定义&#xff1a;模拟极端负载场景验证系统性能极限 目的&#xff1a;发现性能瓶颈、评估系统可靠性、验证容错能力 常见类型&#xff1a;负载测试、压力测试、稳定性测试、峰值测试 1.2 核心性能指标解析 1.2.1 QP…

嵌入式4-Modbus

1.Modbus Modbus 是一种广泛应用于工业自动化领域的通信协议&#xff0c;用于在不同设备&#xff08;如传感器、PLC、变频器、仪表等&#xff09;之间交换数据。它支持串行通信&#xff08;如 RS232、RS485&#xff09;和以太网通信&#xff08;Modbus TCP&#xff09;&#x…

机器学习-手搓KNN算法

一、简介 K最近邻&#xff08;K-Nearest Neighbors, KNN&#xff09;​ 是一种简单且直观的监督学习算法&#xff0c;适用于分类和回归任务。其核心思想是&#xff1a;​相似的数据点在特征空间中彼此接近。KNN通过计算新样本与训练数据中各个样本的距离&#xff0c;找到最近的…

Linux|fork命令及其使用的写时拷贝技术

fork复制进程 fork通过以下步骤来复制进程&#xff1a; 分配新的进程控制块&#xff1a;内核为新进程分配一个新的进程控制块&#xff08;PCB&#xff09;&#xff0c;用于存储进程的相关信息&#xff0c;如进程 ID、状态、寄存器值、内存指针等。复制进程地址空间&#xff1…

Hoppscotch 开源API 开发工具

Hoppscotch 是一个开源的 API 开发工具&#xff0c;旨在为开发者提供一个轻量级、快速且功能丰富的 API 开发和调试平台。以下是对其主要特性和功能的详细介绍&#xff1a; 1. 轻量级与高效 Hoppscotch 采用简约的 UI 设计&#xff0c;注重易用性和高效性。它支持实时发送请求…

Datawhale大语言模型-Transformer以及模型详细配置

Datawhale大语言模型-Transformer以及模型详细配置 Transformer模型位置编码前馈层网络注意力机制多头自注意力编码器解码器 大语言模型的参数配置归一化激活函数位置编码旋转位置编码代码内容实现 注意力机制 参考资料 Transformer模型 当前主流的大语言模型都基于 Transform…

iPhone 16怎么编辑图片?图片编辑技巧、软件分享

在当今这个视觉信息爆炸的时代&#xff0c;一张经过精心编辑的图片往往能够瞬间抓住观众的眼球&#xff0c;而 iPhone 16凭借其卓越的硬件性能和丰富的软件生态&#xff0c;在图片编辑领域展现出了非凡的实力&#xff0c;成为众多摄影爱好者和创意工作者的得力助手。 一、编辑效…

代码随想录_动态规划

代码随想录 动态规划 509.斐波那契数 509. 斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n…

【虚幻引擎UE5】SpawnActor生成Character实例不执行AI Move To,未初始化AIController的原因和解决方法

虚幻引擎版本&#xff1a;5.5.4 问题描述 刚创建的Third Person项目里&#xff0c;定义一个BP_Enemy蓝图&#xff0c;拖拽到场景中产生的实例会追随玩家&#xff0c;但SpawnActor产生的实例会固定不动。BP_Enemy蓝图具体设计如下&#xff1a; BP_Enemy的Event Graph ​​ 又定义…