我也来写KMP

KMP算法(附带手写图解) 给定一个字符串 S,以及一个模式串 P,所有字符串中只包含大小写英文字母以及阿拉伯数字。模式串 P 在字符串 S中多次作为子串出现。求出模式串 P 在字符串 S 中所有出现的位置的起始下标。 阅读详情

网上看了很多关于KMP算法,唉,毕竟不是中国人自己写出来的东西,所以有的人乱写一通(当然,在您眼中,我或许也是),比如KMP算法中有一个公式,对着这个公式进行得出next数组的值,比如下面:

(1)next[0]= -1 意义:任何串的第一个字符的模式值规定为-1。
(2)next[j]= -1   意义:模式串T中下标为j的字符,如果与首字符
相同,且j的前面的1—k个字符与开头的1—k
个字符不等(或者相等但T[k]==T[j])(1≤k<j)。
如:T=”abCabCad” 则 next[6]=-1,因T[3]=T[6]
(3)next[j]=k    意义:模式串T中下标为j的字符,如果j的前面k个
字符与开头的k个字符相等,且T[j] != T[k] (1≤k<j)。
                       即T[0]T[1]T[2]。。。T[k-1]==
T[j-k]T[j-k+1]T[j-k+2]…T[j-1]
且T[j] != T[k].(1≤k<j);
(4) next[j]=0   意义:除(1)(2)(3)的其他情况。

 

我个人觉得如果是要对照公式的话,KMP还有什么意义呢(噢噢噢,理解可以方便一点)?

下面我也在网上找了些资料,ctrl+C和ctrl_V一下,然后再自己修改下。

先贴上代码吧,不一定对。

 

 

 

再说下思路:

构造next数组,next数组含义:next[j]表示j前面出现的K个字符(不包括K本身),与下表为0起的K个字符相同,数学表达即:

T[0]T[1]...T[k-1] 与 T[j-k]...T[j-1]是相同的,所以

next[0]=-1,next[1]=0.....

(next数组的含义要想充分了解的话,做这两个题:PKU 2406 和 PKU 1961,包准你事半功倍!!!)。

然后nextVal数组,是为了与next数组想区别,也可以称作修正next数组或者改进next数组,我们可以看到:

当我们分析到模式串中的第i位于目标串不同时 求得应该从K位开始比较 但是如果第K位于第i位相同的时候,第K位一定与目标串也不同因此应该再次改成当K位比较不同时的NEXT值 即 NEXT[K]。

(以下划横线的是需要证明的,没兴趣的同学可略过)
(转自:http://www.cppblog.com/sicheng/archive/2006/10/10/13537.html)

由于NEXT是由左向右推出来的 所以只需修正一次 (自己想着证明吧)

另外,程序没有使用一个数组来保存未修正时的NEXT值 而直接用J来充当这个功能 但是J是由NEXT(已修正)得来的 那么有没有可能J得不到正确的值?
这个问题最先是我自己想的 后来验证了一下 J一定能够得到正确的值
下面我们来分析一下
下标                         0  1  2  3  4  5  6  7  8  9 10 11 1213
目标串                     0  1  0  0  1  0  1  0  1  0  0   0   0  1
j(未修正的next)       -1 0  0  1  1  2  3  2  3  2  3   4   1  1
修正了的next          -1 0 -1  1  0 -1  3 -1 3 -1  1  4   1   0
让我们看看但模式串比较到了12位的时候(下标为11)
next[11] = 4; next[4] = 0; j|4 = 1...
这时候next[4]拿到的并不是正确的J值!!!
这会导致什么?会导致略过一个比较 即p[11]与p[1]的比较被略过!直接比较了p[11]与p[0]!
是否可以略过这个比较?!
答案是肯定的.
根据逻辑推理 如果p[11]与p[4]不等 而p[4] = p[1]那么p[11]与p[1]一定不等 所以可以略过
这样说似乎很牵强 我们再回想一下NEXT数组的意义 即当我们比较到i位时不等 应该由哪一位重新开始比较 而实际上 这个过程相当于在 7-11的这个串中查找0-3!所以根据NEXT数组的意义 我们也可以知道 这里并不会导致错误 由于被略去的比较一定不需比较 因此 J始终可以得到正确的未修正的NEXT值!

 

 

好吧,下面我们来列举其他例子:

(转自:http://www.slyar.com/blog/kmp-next-nextval.html)

 

计算前缀 Next[i] 的值:

next[0] = -1;定值。
next[1] = 0;s[1]前面没有重复子串。
next[2] = 0;s[2]前面没有重复子串。
next[3] = 0;s[3]前面没有重复子串。
next[4] = 1;s[4]前面有重复子串s[0] = 'a'和s[3] = 'a'。
next[5] = 2;s[5]前面有重复子串s[01] = 'ab'和s[34] = 'ab'。
next[6] = 3;s[6]前面有重复子串s[012] = 'abc'和s[345] = 'abc'。
next[7] = 4;s[7]前面有重复子串s[0123] = 'abca'和s[3456] = 'abca'。

计算修正后的 Nextval[i] 值:

nextval[0] = -1;定值。
nextval[1] = 0;s[1] != s[0],nextval[1] = next[1] = 0。
nextval[2] = 0;s[2] != s[0],nextval[2] = next[2] = 0。
nextval[3] = -1;s[3] == s[0],nextval[3] = nextval[0] = -1。
nextval[4] = 0;s[4] == s[1],nextval[4] = nextval[1] = 0。
nextval[5] = 0;s[5] == s[2],nextval[5] = nextval[2] = 0。
nextval[6] = -1;s[6] == s[3],nextval[6] = nextval[3] = -1。
nextval[7] = 4;s[7] != s[4],nextval[7] = next[7] = 4。

 

好了,KMP要想完全理解,真的不是一朝一夕之功,好运~

 

 

 

夜深人静写算法(十七)- KMP * 本文主要介绍字符串匹配算法(比如:查询一个字符串是否是另一个字符串的子串) 阅读详情

相关推荐

【从零开始学Skynet】基础篇(一):Skynet环境搭建

Skynet运行于Linux操作系统,我们可以在自己的电脑上搭建虚拟机系统,也可以购买阿里云、腾讯云服务器,笔者这个系列的所有代码都是在Ubuntu16.04版本的虚拟机系统下运行编辑。

我是一条寻水的鱼 3167

小甲鱼—手写版KMP代码实现

改了两个小时,竟然是S,T在调用的时候传反了QAQ。

2301_80488393的博客 246

BH1750光强度传感器Stm32f103驱动(已测试ok)

1. 实验:Stm32f103 驱动 bh1750采集光照强度,串口打印采集到的数据。 2. 实验准备器材 开发版:stm32f103c8t6 器件:bh1750 GY-302 开发环境:win10,KILE4 下载程序的软件:FlyMcu.exe 串口调试助手:ComAssistant.exe 3. BH1750 的接线 VCC:5V或3.3V ...

weixin_53329977的博客 8924

kmp算法理解及手写代码

kmp算法 kmp算法是比对str1(长度为n)中是否包含str2(长度为s)的算法。 小tips:暴力解的方法,就是O(sn),但看下面这个例子: a与d不同,说明字符串不匹配,此时若为暴力解,将变成下面这个样子。 又从头开始匹配,但看kmp算法接下来会怎么做? 这是为什么? kmp算法本质是了解自身寻找字符串的特点而避免重复匹配加速暴力算法的过程 在刚开始图中 acac与acac都是匹配成功的,且str2字符串d前满足一个特点 A...A A...A A...A 即首尾是相同的(A=ac )

hch977的博客 664

避开地图定位的坑:手把手教你处理GCJ-02和WGS-84坐标转换(2023最新版)

本文深入解析了GCJ-02与WGS-84坐标系转换的核心原理与常见误区,提供了详细的代码实现与精度控制方法。针对地图定位开发中的实际痛点,文章重点阐述了如何通过迭代逼近法实现高精度坐标转换,并给出了误差测试与业务场景下的工程实践指南,帮助开发者有效规避定位漂移等问题。

lstm7chronicler的博客 1166

基于继电器与三极管的自动水泵控制器DIY:从电路原理到PCB制作实战

继电器作为一种利用电磁原理实现电路通断控制的电气开关,其核心价值在于通过小电流信号控制大电流负载,实现强弱电之间的安全隔离。在自动化控制领域,继电器常与三极管等半导体器件配合,构成驱动电路,将微弱的传感器信号放大,从而可靠地控制电机、水泵等执行机构。这种组合技术广泛应用于工业控制、智能家居及各类电子DIY项目中,例如实现水箱水位的自动检测与控制。本文将以一个典型的自动水泵控制器项目为例,深入剖析如何利用继电器与三极管搭建水位检测与驱动电路,并详细讲解从电路设计、PCB自制(热转印法)到系统调试的完整工程实践

weixin_31774841的博客 346

手写kmp 算法

手写kmp 算法

helloabc123456的博客 451

基于PSINS的INS/NHC/ODO组合导航仿真全解析

组合导航通过多传感器融合克服单一导航系统的局限,是车辆自主定位的关键技术。其中惯性导航(INS)依靠陀螺仪与加速度计积分推算运动状态,但误差随时间累积;GNSS提供绝对位置,却在城市峡谷中易受多径效应和遮挡影响导致定位漂移。卡尔曼滤波作为信息融合核心,将不同量测按统计特性加权,实现优势互补。基于PSINS开源工具箱搭建的SINS/GNSS/ODO/NHC组合导航仿真,能够在GNSS失锁条件下利用非完整约束和里程计抑制惯性误差发散,广泛应用于无人驾驶、物流车辆自主定位等场景。本文围绕PSINS仿真环境,详细拆

weixin_29044713的博客 252

浅谈 KMP 算法

面试官夺命三连 KMP 是啥?KMP 能干啥?手写 KMP ? 在计算机科学中,Knuth-Morris-Pratt字符串查找算法(简称为KMP算法)可在一个主文本字符串S内查找一个词W的出现位置。此算法通过运用对这个词在不匹配时本身就包含足够的信息来确定下一个匹配将在哪里开始的发现,从而避免重新检查先前匹配的字符。 这个算法是由高德纳(Donald Ervin Knuth)和...

Shelby Lee的博客 713

生物信息学投稿避坑指南:如何根据影响因子和审稿速度选择最适合的期刊

本文为生物信息学研究者提供全面的期刊投稿策略,重点解析影响因子、审稿速度等关键指标,帮助选择最适合的期刊。涵盖算法开发类和应用型研究的投稿路径,分析不同出版社特点及开放获取的利弊,并提供投稿全流程优化建议,助力高效发表研究成果。

weixin_42652674的博客 378

【ubuntu24.04】auto remove后,重启,kernel panic ,please reboot your computer vfs unable to mount root fs

Ubuntu 24.04系统在运行auto remove后出现内核恐慌(kernel panic)无法启动,显示"VFS: unable to mount root fs"错误。该问题是由于当前内核被清除导致系统无法挂载根分区。解决步骤包括:1)尝试用GRUB菜单中的旧内核启动;2)在GRUB中临时编辑启动参数;3)使用Ubuntu启动盘进行chroot修复;4)使用Boot-Repair工具一键修复。成功启动后,需要重新安装linux-generic等元包,重建initramfs并更新

突围 1205

我写的KMP 算法

#include#include#includeusing namespace std;void init(string ,string);void show(char [],int);int kmp(string ,string,int pos);void get_next(char*,int *);string s1,t1;int m,n;char *s;char *t;int *next;/

jjduan185的专栏 1484

多体动力学分析软件:SIMPACK_(17).SIMPACK高级编程与脚本

自定义力和约束可以用于模拟更复杂和现实的物理场景。SIMPACK 提供了接口,允许用户通过 Python 脚本来实现自定义力和约束。以下是一个示例,展示如何定义一个自定义力函数并应用于模型。# 定义自定义力函数"""自定义力函数:param t: 时间:param position: 位置:param velocity: 速度:return: 力"""# 创建一个新的 SIMPACK 模型# 添加一个刚体# 添加一个关节# 添加一个自定义力# 设置仿真参数# 运行仿真。

kkchenjj的博客 1418

我来写KMP算法

KMP算法是(Knuth-Morris-Pratt)提出的一种算法,其核心思想是通过分析子串来实现串匹配过程中不回溯。这样对于高频查找,还有长字串查找十分有帮助。首先我们来看看普通的回溯查找:朴素的查找算法最让人头疼的就是回溯,一旦一次匹配不成功,主串 字串都要回溯,主串回溯到到以前的位置的下一个位置,字串直接回溯到开始处。所以我们可以计算其时间复杂度为: 最坏情况O(mn)其中m为主串长

xjtufjj的专栏 1055

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

大哥可以写KMP该——达到strstr()

在最后采访,面试官要求实现strstr(),当场就蒙了。这个题目是模式匹配问题。《算法导论》里列出了几种字符串匹配算法: 朴素算法 | Rabin-Karp | 有限自己主动机算法 | Knuth-Morris-Pratt (KMP) 各种方法都有自己的优缺点,我认为,另一些方法能够參考: 1)比方像求最长公共子串那样,用动态规划...

weixin_30384217的博客 109

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

自己写的KMP板子

//获取匹配个数 #include using namespace std; const int maxn = 5005; int nt[maxn]; char a[maxn], b[maxn]; void GetNext(char b[], int blen) { int j = 0, k = -1; nt[0] = -1; --blen;

yo_bc的博客 348

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【KMP模板】简单写个KMP~

本来easy的KMP 却一直过不了洛谷的模板题。。。 仔细一看原来在输出next数组时打的回车而不是空格。。。 身败名裂。。。 话说有个sunday貌似一般状况下比KMP快呢。。。去看看2333 #include<cstdio> #include<iostream> #include<cstring> #include<algorith...

weixin_30445169的博客 99

用c++写一个KMP算法

KMP算法是一种字符串匹配算法,可以快速在文本串中找到模式串的出现位置。 下面是一个用C语言实现的KMP算法的示例代码: ```c #include <stdio.h> #include <string.h> // 计算 next 数组 void get_next(char *p, int *next) { int p_len = strlen(p); ne...

weixin_35751194的博客 174

转载一篇写KMP算法写得非常好的博文

KMP算法详解

Simon_coder的博客 1000

自写KMP模板

1 int* Getnext(char *p,int len_p){//p为模式串 2 int *Next = new int[len_p]; 3 Next[0] = -1; 4 int j = -1,i=0; 5 while(i < len_p){//自身与自身匹配 6 while(j != -1&&am...

weixin_30463341的博客 71

我写的KMP算法代码

<br />#include<stdio.h><br />#include<string.h><br />int Index(char *s,char *t,int pos)  //普通算法<br />{<br /> int i = pos;<br /> int j = 0;<br /> int len1,len2;<br /> len1 = strlen(s);<br /> len2 = strlen(t);<br /> while (i<len1&&j<len2)<br /> {<br />  if (

yj0821421350的专栏 334

KMP算法-自写自用版

自己边捋边写了一遍,大彻大悟了,遂存之。

m0_67871160的博客 432

用erlang写的kmp算法

Knuth-Morris-Pratt 字符串查找算法,简称为 “KMP算法”,常用于在一个文本串S内查找一个模式串P 的出现位置,这个算法由Donald Knuth、Vaughan Pratt、James H. Morris三人于1977年联合发表,故取这3人的姓氏命名此算法。 KMP算法对比暴力匹配算法的优势是:KMP算法通过分析模式串,找出模式串中相同的前缀和后缀,这样在匹配失败,移...

weixin_30767835的博客 165

用Python简单写一个KMP

KMP 简单写一个KMP算法: def Transform_Table(pattern): state = len(pattern) table = [[0 for _ in range(256)] for _ in range(state)] X = 0 table[0][ord(pattern[0])] = 1 for i in range(1, len(pattern)): current_char = ord(pattern[i])

ab459548764的博客 474

看到一篇博客写的kmp算法,由于才疏学浅,难以理解,干脆自己实现个kmp算法

KMP字符串模式匹配详解 来自优快云     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法。简单匹配算法的时间复杂度为O(m*n);KMP匹配算法。可以证明它的时间复杂度为O(m+n).。 一.  简单匹配算法 先来看一个简单匹配算法的函数: int Index_BF ( char S [ ], char T [ ], int po

BpLife 776

哥也能写KMP了——实现strstr()

经过上次去面试,面试官要求实现strstr(),当场就蒙了,KMP该怎么写啊,这是又要挂了。不行,不能再栽在这里了,不能再菜下去了,于是,立马抄起书《数据结构(C语言版)》,看了一下,感觉,KMP实现起来,代码是很少的,效率还算可以了,实现的过程中,难就难在如何构造next[] 数组,以及如何理解next[],对避免指针无效回退的作用。看了一个上午,总算是明白了。现就贴下代码,做下笔记。 #

1440
上一篇: 将文件之间的编译依赖关系降至最低
下一篇: 运用比较器实现机制(函数对象和指针对象)实现最大堆和最小堆
MagicxiaoZ
博客等级 码龄19年 5粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值