【进阶KMP算法】nextval手算代码均有详解(每步配图)

这里是进阶,所以如果有小伙伴不知道KMP算法是什么的话,请看上一章(写的很清楚),故我这里概念什么的就不再过多描述。

引入:

要改进那么肯定要知道,哪里有不足,我们假设目标串s为“aaabaaaab”,模式串t为"aaaab",模式串t对应的next数组如下面的图所示。


 KMP算法比较图大家看看就会发现哪里能改进

由于图比较长所以我分成几份发,最后有一个总的如果可以保存的话大家直接看最后一个就行。


总图片


我们发现一共需要12次字符比较,我们看到t[0]t[1]t[2]t[3]这几个字符相同,所以如果t[3]不行,那么t0,1,2是不是都没有比较的意义了,这里就是我们能改进的。

改进主要体现在next数组的求解中

改进:nextval

我先给出代码,大家看看和next数组有什么不同的地方

void GetNextval(char*t,int nextval[])
{int j=0,k=-1;int length = strlen(t);nextval[0] = -1;while(j<length-1){if(k==-1||t[j]==t[k]){j++;k++;if(t[j]!=t[k]){nextval[j] = k;}else nextval[j] = nextval[k];}else k = nextval[k];}
}

我们发现,是在while里面多了if判断语句,这个就是来实现,上面图中要改进的地方。如果不知道next数组怎么求还是先看看我前面写的文章,nextval是基于next数组来写的。大家可以好好理解一下。

下面我讲讲nextval怎么手算(可以用来考试)

总结出来就一句话(相同用下面,不同用next)

详解:红色为重点要看的

首先看next【2】为0,接着看t【0】和t【2】(因为此时不同点在2)相同故nextval【2】用下面nextval【0】=-1,如果不相同直接用上面的next【2】=0.下面的类似。


因为t【5】!=t【3】所以nextval【5】 = next【5】 = 3.

下面我给出一个t数组大家算算next和nextval看看掌握了没有,答案后面给出

手算例题

答案:

大家一定要先自己写完再看答案。

总代码

c++

//改进的KMP算法
#include "sqstring.cpp"
void GetNextval(SqString t,int nextval[])  //由模式串t求出nextval值
{int j=0,k=-1;nextval[0]=-1;while (j<t.length) {if (k==-1 || t.data[j]==t.data[k]) {	j++;k++;if (t.data[j]!=t.data[k]) nextval[j]=k;else  nextval[j]=nextval[k];}else  k=nextval[k];    	}}
int KMPIndex1(SqString s,SqString t)    //修正的KMP算法
{int nextval[MaxSize],i=0,j=0;GetNextval(t,nextval);while (i<s.length && j<t.length) {if (j==-1 || s.data[i]==t.data[j]) {	i++;j++;	}else j=nextval[j];}if (j>=t.length)  return(i-t.length);elsereturn(-1);
}
int main()
{SqString s,t;StrAssign(s,"ababcabcacbab");StrAssign(t,"abcac");printf("s:");DispStr(s);printf("t:");DispStr(t);printf("位置:%d\n",KMPIndex1(s,t));return 1;
}

c语言

#define  _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void GetNextval(char* t, int nextval[])
{int j = 0, k = -1;int length = strlen(t);nextval[0] = -1;while (j < length - 1){if (k == -1 || t[j] == t[k]){j++; k++;if (t[j] != t[k]){nextval[j] = k;}else nextval[j] = nextval[k];}else k = nextval[k];}
}
int KMPIndex(char* haystack, char* needle) {int i = 0, j = 0;int length1 = strlen(haystack);int length2 = strlen(needle);int nextval[100];//可变GetNextval(needle, nextval);while (i < length1 && j < length2){if (j == -1 || haystack[i] == needle[j]){i++; j++;}else j = nextval[j];}if (j >= length2) return i - length2;else return -1;
}
int main()
{char str1[] = "aaabaaaab";char str2[] = "aaaab";int k = KMPIndex(str1, str2);printf("%d", k);return 0;
}

上面给出的c语言和c++的代码均经过调试,大家可放心使用。

例题力扣例题28(推荐BF和KMP算法都用一下,特别是KMP)

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固自己的知识点,和一个学习的总结,对文章有任何问题的还请指出,接受大家的批评,让我改进,如果大家有所收获的话还请不要吝啬你们的点赞和收藏,这可以激励我写出更加优秀的文章。

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

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

相关文章

c# 捕获全部线程的异常 试验

1.概要 捕获全部线程的异常 试验&#xff0c;最终结果task的异常没有找到捕获方法 2.代码 2.1.试验1 2.1.1 试验结果 2.2 代码 2.2.1主程序代码 using NLog; using System; using System.Threading; using System.Windows.Forms;namespace 异常监控 {static class Program…

C++继承与派生——(8)多继承

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 苦难和幸福一样&#xff0c;都是生命盛…

Java API 操作Docker浅谈

背景&#xff1a; 使用com.github.docker-java库可以很方便地在Java中操作Docker。下面是一个详细的教程&#xff0c;包括创建镜像、创建容器、启动容器、停止容器和删除容器的步骤以及每一步的说明。 前提&#xff1a; 首先&#xff0c;在你的Java项目中添加com.github.doc…

gRPC之内置Trace

1、内置Trace grpc内置了客户端和服务端的请求追踪&#xff0c;基于golang.org/x/net/trace包实现&#xff0c;默认是开启状态&#xff0c;可以查看事 件和请求日志&#xff0c;对于基本的请求状态查看调试也是很有帮助的&#xff0c;客户端与服务端基本一致&#xff0c;这里…

c++写入数据到文件中

假设你想编写一个C程序&#xff1a;当你在调试控制台输入一些数据时&#xff0c;系统会自动存入到指定的文件中&#xff0c;该如何操作呢&#xff1f; 具体操作代码如下&#xff1a; #include<iostream> #include<string> #include<fstream> using namespa…

服务器硬件及RAID配置实战

目录 1、RAID的概念 2、RAID的实现方式 3、标准的RAID 3.1 RAID 0 3.2 RAID 1 3.3 RAID 5 3.4 RAID 10 4、建立硬件 RAID的过程步骤 1、进入RAID 1.1 重启服务器 1.2 进入RAID界面 1.3 在RAID界面切换目录 2、创建RAID 2.1 移动到RAID卡 2.2 按F2&#xff0c;选择…

AspectJWeaver之Gadget分析

前言&#xff1a; 今天看了下ysoserial的AspectJWeaver方法&#xff0c;分析了下其是如何通过调用SimpleCache$StorableCachingMap来实现写文件&#xff0c;这里把分析的流程写下来&#xff1a; 首先我们要看下其所需要的jar包&#xff1a; <dependencies><dependen…

redis 从0到1完整学习 (十二):RedisObject 之 List 类型

文章目录 1. 引言2. redis 源码下载3. redisObject 管理 List 类型的数据结构3.1 redisObject 管理 List 类型3.2 List PUSH 源码 4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1…

SQL性能优化-索引

1.性能下降sql慢执行时间长等待时间长常见原因 1&#xff09;索引失效 索引分为单索、复合索引。 四种创建索引方式 create index index_name on user (name); create index index_name_2 on user(id,name,email); 2&#xff09;查询语句较烂 3&#xff09;关联查询太多join&a…

边缘计算网关在温室大棚智能控制系统应用,开启农业新篇章

项目需求 ●目前大棚主要通过人为手动控温度、控水、控光照、控风&#xff0c;希望通过物联网技术在保障产量的前提下&#xff0c;提高作业效率&#xff0c;降低大棚总和管理成本。 ●释放部分劳动力&#xff0c;让农户有精力管理更多大棚&#xff0c;进而增加农户收入。 ●…

WEB 3D技术 three.js通过光线投射 完成几何体与外界的事件交互

本文 我们来说 光线投射 光线投射技术是用于3维空间场景中的交互事件 我们先编写代码如下 import ./style.css import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";const scene new THRE…

使用 extract + TextMapAdapter 实现了自定义 traceId

前言 某些特定的场景&#xff0c;需要我们通过代码的方式实现自定义 traceId。 实现思路&#xff1a;通过 tracer.extract 能够构造出 SpanContext &#xff0c;将构造出来的 SpanContext 作为上层节点信息&#xff0c;通过 asChildOf(SpanContext) 能够构造出当前的 span。 …