KMP入门级别算法详解--终于解决了(next数组详解)

对于正常的字符串模式匹配,主串长度为m,子串为n,时间复杂度会到达O(m*n),而如果用KMP算法,复杂度将会减少线型时间O(m+n)。

设主串为ptr="ababaaababaa";,要比较的子串为a=“aab”;

KMP算法用到了next数组,然后利用next数组的值来提高匹配速度,我首先讲一下next数组怎么求,之后再讲匹配方式。

1、next数组详解

首先是理解KMP算法的第一个难关是next数组每个值的确定,这个问题困恼我很长时间,尤其是对照着代码一行一行分析,很容易把自己绕进去。

定义一串字符串

ptr = "ababaaababaa";

next[i](i从1开始算)代表着,除去第i个数,在一个字符串里面从第一个数到第(i-1)字符串前缀与后缀最长重复的长度。(这里看不懂继续往下看就行)

2、什么是前缀?

在“aba”中,前缀就是“ab”,除去最后一个字符的剩余字符串。

同理可以理解后缀。除去第一个字符的后面全部的字符串。

在“aba”中,前缀是“ab”,后缀是“ba”,那么两者最长的子串就是“a”;

在“ababa”中,前缀是“abab”,后缀是“baba”,二者最长重复子串是“aba”;

在“abcabcdabc”中,前缀是“abcabcdab”,后缀是“bcabcdabc”,二者最长重复的子串是“abc”;

这里有一点要注意,前缀必须要从头开始算,后缀要从最后一个数开始算,中间截一段相同字符串是不行的。

在next数组中,有两种定义方式:(定义方式可以先不用管,继续往下看,看懂了再回来看)

第一种是next[1]=-1,next[2]=-1。这里的-1代表没有匹配,1代表匹配了1位。

第二种是规定next[1]=0,next[2]=1。(第二种方法之后会讲)这里0与1是规定,后面的匹配中,如果1位匹配,则规定next值为2(就是匹配的位数+1)。

3、先看第一种规定方法:

再回到next[i]的定义,对于字符串ptr = "ababaaababaa";

next[1] = -1,字符串“a”,要进行next数组运算,也就是代表着除了第一个元素,它本身之前的 前缀 与 后缀 最长的重复子串,这里是空 ,即"",没有,我们记为-1,代表空。(0代表1位相同,1代表两位相同,依次累加)。

next[2] = -1,字符串为“ab”,要进行计算的字符串为“a”(要扣除当前字符“b”,所以只剩下“a”),没有前缀与后缀,故最长重复的子串是空,值为-1;

next[3] = -1,字符串为“aba”,要进行计算的字符串为“ab”(要扣除当前字符“a”,所以只剩下“ab”),前缀是“a”,后缀是“b”,最长重复的子串“”;

next[4] = 1,字符串为“abab”,要进行计算的字符串为"aba"(要扣除当前字符“b”,所以只剩下“aba”),前缀是“ab”,后缀是“ba”,最长重复的子串“a”;next数组里面就是最长重复子串字符串的长度

next[5] = 2,字符串为“ababa”,要进行计算的字符串为"abab"(要扣除当前字符“a”,所以只剩下“abab”),前缀是“aba”,后缀是“bab”,最长重复的子串“ab”;

next[6] = 3,字符串为“ababaa”,要进行计算的字符串为"ababa"(要扣除当前字符“a”,所以只剩下“ababa”),前缀是“abab”,后缀是“baba”,最长重复的子串“aba”;

next[7] = 1,字符串为“ababaaa”,要进行计算的字符串为"ababaa"(要扣除当前字符“a”,所以只剩下“ababaa”),前缀是“ababa”,后缀是“babaa”,最长重复的子串“a”;

next[8] = 1,字符串为“ababaaab”,要进行计算的字符串为"ababaaa"(要扣除当前字符“b”,所以只剩下“ababaaa”),前缀是“ababaa”,后缀是“babaaa”,最长重复的子串“a”;

next[9] = 2,字符串为“ababaaaba”,要进行计算的字符串为"ababaaab"(要扣除当前字符“a”,所以只剩下“ababaaab”),前缀是“ababaaa”,后缀是“babaaab”,最长重复的子串“ab”;

next[10] = 3,字符串为“ababaaabab”,要进行计算的字符串为"ababaaaba"(要扣除当前字符“b”,所以只剩下“ababaaaba”),前缀是“ababaaab”,后缀是“babaaaba”,最长重复的子串“aba”;

next[11] = 4,字符串为“ababaaababa”,要进行计算的字符串为"ababaaabab"(要扣除当前字符“a”,所以只剩下“ababaaabab”),前缀是“ababaaaba”,后缀是“babaaabab”,最长重复的子串“abab”;

next[12] = 5,字符串为“ababaaababaa”,要进行计算的字符串为"ababaaababa"(要扣除当前字符“a”,所以只剩下“ababaaababa”),前缀是“ababaaabab”,后缀是“babaaaababa”,最长重复的子串“ababa”;

所以字符串ptr = "ababaaababaa"的next数组为:-1,-1,-1,1,2,3,1,1,2,3,4,5

4、第二种方法中:

变化的只有下标,原理都一样。

这里我们定义next[1] = 0 , next[1] = 1;

再分析ptr字符串,ptr = "ababaaababaa";

跟上一个的情况类似,

next[1] = 0 ,事先定义好的

next[2] = 1 ,事先定义好的

next[3] = 1 ,最长重复的子串“”;1代表没有重复,2代表有一个字符重复。

next[4] = 2 ,最长重复的子串“a”;追偿的长度加1,即为2.

next[5] = 3 ,以下都跟之前的一样,这种方法是最长的长度再加上一就可以了。

next[6] = 4

next[7] = 2

next[8] = 2

next[9] = 3

next[10] = 4

next[11] = 5

next[12] = 6

以上是next数组的详细解释。next数组求值 是比较麻烦的,剩下的匹配方式就很简单了。

next数组用于子串身上,根据上面的原理,我们能够推出子串a=“aab”的next数组的值分别为0,1,2.(按照我说的第二种方式算的)。

首先开始计算主串与子串的字符,设置主串用i来表示,子串用j来表示,如果ptr[i]与a[i]相等,那么i与j就都加1:

prt[1]与a[1]相等,i++,j++:

用代码实现就是

if( j==0 ||  ptr[i]==a[j])
{
        ++i;
        ++j;
}

ptr[2]与a[2]不相等

此时ptr[2]!=a[2],那么令j = next[j],此时j=2,那么next[j] = next[2] = 1.那么此时j就等于1.这一段判断用代码解释的话就是:

if( ptr[i]!=a[j])
{
        j = next[j];
}
加上上面的代码进行组合:

在对两个数组进行比对时,各自的i,j取值代码:

while( i<ptr.length && j< a.length)
{
        if( j==0 || ptr[i]==a[i] )
        {
                ++i;
                ++j;
                next[i] = j;
        }
        else
         {
                j = next[j];
        }
}

此时将a[j]置于j此时所处的位置,即a[1]放到j=2处,因为在j=2时出现不匹配的情况。

此时再次计算是否匹配,可以看出来a[1]!=ptr[2],那么j = next[j],即此时j = next[1] = 0;

根据上面的代码,当j=0时,执行++i;++j;

此时就变为:

此时ptr[3] = a[1],继续向下走,下一个又不相等了,然后“aab”向后挪一位,这里不再赘述了,主要的思想已经讲明白了。到最后一直到i = 8,j=3时匹配成功,KMP算法结束。整个过程就结束了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MFC窗体背景颜色的设置、控件白色背景问题、控件文本显示重叠问题、被父窗体背景覆盖的问题

文章目录 设置mfc窗体背景颜色窗体设置背景颜色后解决控件白色背景解决重复修改控件文本后重叠的问题自绘控件被父窗体背景覆盖的问题 设置mfc窗体背景颜色 设置窗体的背景颜色非常简单&#xff0c;只需要在窗体的OnEraseBkgnd里面填充窗体背景就可以了&#xff0c;甚至直接画…

【SpringCloud】-GateWay源码解析

GateWay系列 【SpringCloud】-GateWay网关 一、背景介绍 当一个请求来到 Spring Cloud Gateway 之后&#xff0c;会经过一系列的处理流程&#xff0c;其中涉及到路由的匹配、过滤器链的执行等步骤。今天我们来说说请求经过 Gateway 的主要执行流程和原理是什么吧 二、正文 …

30. MVC设计模式

JavaEE 开发流程 ↓MVC的概念 MVC是Model-View-Controller的简称&#xff0c;即模型-视图-控制器。 MVC是一种设计模式&#xff0c;它把应用程序分成三个核心模块&#xff1a;模型、视图、控制器&#xff0c;它们各自处理自己的任务。 模型(model) 模型是应用程序的主体部分…

JavaEE进阶学习:Spring MVC 程序开发

1.什么是 Spring MVC Spring Web MVC 是基于Servlet API 构建的原始 Web 框架&#xff0c;从一开始就包含在Spring 框架中。它的正式名称 “Spring Web MVC” 来自其源模块的名称(Spring-webmvc)&#xff0c;但它通常被称为“Spring MVC”。 从上述定义我们可以得出两个关键信…

每日一题——轮转数组

1. 题目描述 给定一个整数数组nums&#xff0c;将数组中的元素向右轮转k个位置&#xff0c;其中k是非负数。 示例1: 输入&#xff1a;nums [1,2,3,4,5,6,7]&#xff0c;k 3 输出&#xff1a;[5,6,7,1,2,3,4] 解释&#xff1a; 向右轮转 1步&#xff1a;[7,1,2,3,4,5,6] 向右…

在Linux下探索MinIO存储服务如何远程上传文件

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 创建Buckets和Access Keys二. Linux 安装Cpolar三. 创建连接MinIO服务公网地…

LED灯驱动模块加载与卸载代码框架

一. 简介 本文来编写 LED灯驱动模块加载与卸载的代码。 二. LED灯驱动模块加载与卸载代码框架 1. 创建工程 我的驱动代码存放目录&#xff1a; ubuntu系统 /home/wangtian/zhengdian_Linux/Linux_Drivers 目录下。 进入 /home/wangtian/zhengdian_Linux/Linux_Drivers 目…

Java开发框架和中间件面试题(4)

27.如何自定义Spring Boot Starter&#xff1f; 1.实现功能 2.添加Properties 3.添加AutoConfiguration 4.添加spring.factory 在META INF下创建spring.factory文件 6.install 28.为什么需要spring boot maven plugin? spring boot maven plugin 提供了一些像jar一样打包…

优先级队列与仿函数

优先级队列 优先级队列 priority_queue 是一种容器适配器&#xff0c;听起来是队列&#xff0c;其实它的底层数据结构是堆&#xff0c;所谓的优先级为默认越大的数优先级越高&#xff0c;即默认为大堆。 使用方式如下面的代码&#xff1a; #include<iostream> #includ…

做抖店需要保证金吗?总共需要多少资金?具体资金投入如下!

我是电商珠珠 做抖店需要保证金吗&#xff1f;这是很多想要入驻的新手常问的问题。我的回答是&#xff0c;需要&#xff01; 抖店平台之所以设立保证金&#xff0c;就是为了约束商家的行为&#xff0c;避免交易市场出现混乱&#xff0c;给用户一个良好的购物体验。 今天呢&a…

【性能优化】MySql数据库查询优化方案

阅读本文你的收获 了解系统运行效率提升的整体解决思路和方向学会MySQl中进行数据库查询优化的步骤学会看慢查询、执行计划、进行性能分析、调优 一、问题&#xff1a;如果你的系统运行很慢&#xff0c;你有什么解决方案&#xff1f; ​关于这个问题&#xff0c;我们通常首先…

Unity中Shader观察空间推导

文章目录 前言一、本地空间怎么转化到观察空间二、怎么得到观察空间的基向量1、Z轴向量2、假设 观察空间的 Y~假设~ (0,1,0)3、X Y 与 Z 的叉积4、Y X 与 Z 的叉积 三、求 [V~world~]^T^1、求V~world~2、求[V~world~]^T^ 四、求出最后在Unity中使用的公式1、偏移坐标轴2、把…

[每周一更]-(第31期):Mysql安装汇总

写自&#xff1a;20230204 23:25 一. mysql rpm二进制包 rpm -Uvh http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm yum install mysql-community-server service mysqld start set password password(“123456”)二. mysql yum安装 1、安装查看有没有安装…

企业级“RAS”的数据平台如何炼成?

从“看报表”到“数据分析结果直接投入运营”&#xff0c;数字化正在深入企业经营&#xff0c;数据系统正在成为核心生产系统。相应的&#xff0c;企业对“作业挂了”、“系统崩了”、“算不出来”的容忍度越来越低——只有足够稳定、可靠、专业的数据系统&#xff0c;才能及时…

智能优化算法应用:基于社交网络算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于社交网络算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于社交网络算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.社交网络算法4.实验参数设定5.算法结果6.…

el-select 全选

<template><div class"container"><el-selectv-model"choosedList"clearablemultiplecollapse-tagsplaceholder"请选择"change"select_Change"><div style"padding: 0 20px; line-height: 34px">&l…

机器学习算法(11)——集成技术(Boosting——梯度提升)

一、说明 在在这篇文章中&#xff0c;我们学习了另一种称为梯度增强的集成技术。这是我在机器学习算法集成技术文章系列中与bagging一起介绍的一种增强技术。我还讨论了随机森林和 AdaBoost 算法。但在这里我们讨论的是梯度提升&#xff0c;在我们深入研究梯度提升之前&#xf…

Python实现AR协方差结构线性回归模型(GLSAR算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 GLSAR是具有AR协方差结构的广义最小二乘法线性回归模型。 本项目通过GLSAR回归算法来构建AR协方差结构…

RocketMQ实践:确保消息不丢失与顺序性的高效策略

一、使用RocketMQ如何保证消息不丢失&#xff1f; 这个是在面试时&#xff0c;关于MQ&#xff0c;面试官最喜欢问的问题。这个问题是所有MQ都需要面对的一个共性问 题。大致的解决思路都是一致的&#xff0c;但是针对不同的MQ产品又有不同的解决方案。分析这个问题要从以 下几…

02|用LangChain快速构建基于“易速鲜花”本地知识库的智能问答系统

02&#xff5c;用LangChain快速构建基于“易速鲜花”本地知识库的智能问答系统 项目及实现框架 我们先来整体了解一下这个项目。 项目名称&#xff1a;“易速鲜花”内部员工知识库问答系统。 项目介绍&#xff1a;“易速鲜花”作为一个大型在线鲜花销售平台&#xff0c;有自…