KMP算法详解

KMP算法代码详解 学习了kmp算法,思想其实很好理解,但是代码的实现一直看得很迷糊。看了很多博客,特别是对匹配信息的next数组有很多不同,比如数组有首位有-1的也有0的等。我自己也疏离了一遍,记录一下,方便之后以后回忆。 首先KMP算法主要是用来解决字符串(也叫主串)中的模式串定位问题,比如,有一个主串"abaabaabbabaaabaabbabaab",要找出主串中是否存在子串"abaabbabaab",并返回匹配到的具体位置。 如果是普通的暴力匹配,应该是将主串和模式串从左到右一个个匹配,如果这个过程中有某个字符不. 阅读详情

概念

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。

原理

接下来我们先分析三张图,S代表主串,T代表模式串。
当主串S[i]与子串T[j]失配时,i不回溯,仅j回溯到一个尽量“偏右”的位置k。因此 KPM算法的核心问题是寻找确定 k = n e x t [ j ] k=next[j] k=next[j]的方法。
(I)
(II)
(III)
由 (I) ,(II),和 (III) 我们得到:
T[0 … k-1] = T[j-k … j-1] = T[0 … next[j]-1]
因此得到k = next[j]的定义(注意下标范围)

以上定义也说明next[j]与主串S无关。
next[j]函数举例

代码

kmp算法:

void kmp(int *S, int *T) {
    int i = 0, j = 0;
    getnext(T, next);
    while (i < n) {
        if (j == -1 || S[i] == T[j]) {
            i++;
            j++;
        } else
            j = next[j];
        if (j == m) {
            printf("%d\n", i - m + 1);
            return;
        }
    }
    printf("-1\n");
}

根据定义 next[0] = -1;
设 next[j] = k,求 next[j+1]
若 T[j] = T[k],则 next[j+1] = k + 1 = next[j] + 1;
若 T[j] = T[next[k]], 则 next[j+1] = next[k] + 1;
next[j]函数:

void getnext(int *T, int *next) {
    int j = 0, k = -1;
    next[0] = -1;
    while (j < m) {
        if (k == -1 || T[j] == T[k]) {
            j++;
            k++;
            next[j] = k;
        } else
            k = next[k];
    }
}

分析

运用KMP算法的匹配过程

  • 第1趟
    目标 a c a b a a b aa b c a c a a b c
    模式  a b a a b c a c
    j = 1 -> j = f(j-1) + 1 = 0
  • 第2趟 
    目标 a c a b a a b aa b c a c a a b c
    模式 a b a a b c a c
    j = 5->j =f(j-1)+1= 2
  • 第3趟
    目标 a c a b a a b a a b c a c a a b c
    模式    (a b)a a b c a c
    计算失效函数f[j]的方法
    首先确定f[0] = -1,再利用f[j]求f[j+1]。
    KaTeX parse error: Expected group after '\right' at end of input: …nd{array}\right
    其中, f(1)[j] = f[j],
         f(m)[j] = f[f(m-1)[j]]

    kmp算法的复杂度是O(n+m),可以采用均摊分析来解答,具体可参考算法导论。
    注意事项:
    next数组定义为全局变量时,最好不要命名为next,会与库函数重名,提交时会出现编译错误。。。

练习

HDU 1711 Number Sequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711
解题思路:http://blog.youkuaiyun.com/piaocoder/article/details/41928323
POJ 2406 Power Strings
题目链接:http://poj.org/problem?id=2406
解题思路:http://blog.youkuaiyun.com/piaocoder/article/details/47733683
POJ 2752 Seek the Name, Seek the Fame
题目链接:http://poj.org/problem?id=2752
解题思路:http://blog.youkuaiyun.com/piaocoder/article/details/47733303
POJ 3461 Oulipo
题目链接:http://poj.org/problem?id=3461
解题思路:http://blog.youkuaiyun.com/piaocoder/article/details/47732321

【KMP算法详解——适合初学KMP算法的朋友】 KMP算法的初级体验,只为抛砖引玉之用 阅读详情

相关推荐

Ubuntu24.04/20.04设置网络共享文件夹

Ubuntu20.04利用向日葵远程控制时,不能传输文件。使用linux版本QQ来传输是可以的,不过linuxqq功能真的很弱。因此,打算在Ubuntu系统中建立一个共享文件夹,可在局域网中访问。 1、新建共享文件夹 获取root权限,或者登陆root账户。可在/home文件夹(或其它文件夹)下新建一个文件夹,如share。 右击文件夹,选择“本地网络共享”菜单。按下图设置。 点击确定。如果系统已经安装了samba服务器,就可以进入第3步。如果没有,会提示安装,按提示安装,可能会出错,可进.

willhu2008的专栏 2万+

KMP算法部分代码 分析理解

KMP算法部分代码及其分析理解

weixin_67828227的博客 472

【可不卸载重装】VS2019新建项目里没有CUDA选项

问题:VS2019 新建项目里没有CUDA选项,vs也属性没有cuda。这是因为你在Visual Studio 2019安装之前,先安装了CUDA Toolkit。

qq_62844901的博客 1318

KMP算法(失效函数)介绍

代码中 p[j] == p[k] 是这样的情况:这时 k = next[j] ,就是 j 和 k 都已被赋了值的,到 j 这里需要重置了即P[j] 不等于T[i],另外p[0 - (k-1)] == p[(j-k) -(j - 1)] ,"ab"是 P 的前缀字符串"abcab"的“最长的既是真前缀又是后缀的子串"也就是说假如完成了k++,j++的设置,P 的前缀字符串从"abcab"变成"abcabd",而"abcabd"子串的寻找和"abc"子串寻找的结果相同,所以代码是 k = next[k]。...

m0_52293362的博客 2817

手把手教你用运放和基准源,把±10V信号变成ADC能吃的0-4V(附完整计算过程)

本文详细介绍了如何利用OP07运放和REF5040基准源设计工业级信号调理电路,将±10V传感器信号转换为0-4V ADC可接受范围。通过七步流程,包括需求分析、元器件选型、电路设计、理论计算、PCB布局、实测验证与性能优化,帮助工程师解决信号不匹配问题,提升系统精度与稳定性。

weixin_28731223的博客 466

LVGL在STM32H743IIT6上的性能优化技巧:如何提升图形界面刷新速度

本文详细介绍了在STM32H743IIT6高性能MCU上优化LVGL图形界面刷新速度的实战技巧。通过利用芯片的DMA2D硬件加速模块替代低效的软件画点,将绘制缓冲区放入SDRAM并启用双缓冲机制,以及合理配置CPU缓存与MPU,有效解决了界面卡顿问题。文章还涵盖了LVGL引擎调优、内存架构优化等关键步骤,帮助开发者充分发挥STM32H743的硬件潜力,实现流畅的图形界面体验。

vscode6remote的博客 306

KMP学习笔记

KMP(Knuth–Morris–Pratt)算法是一种字符串`模式匹配`算法。核心原理是利用匹配失败后的信息,尽量减少模式串与主串的匹配此处以达到快速匹配的目的。时间复杂度为O(m+n) 它的改进在于,每当从某个起始位置开始一轮匹配后,如果在匹配过程中出现失配,不回溯 i 而是利用已经得到的部分匹配结果将 指针 在 模式 上向右移动(退回)尽可能远的一段距离 再按照规则进行下一轮匹配

虚青海的博客 869

Fortran环境配置:VS2022+Intel oneAPI安装全流程指南

Fortran环境配置:VS2022+Intel oneAPI安装全流程指南

shuyisuisuinian的博客 2万+

KMP算法——快速求失效函数值及其代码实现

前缀和后缀的最大相等长度 为了更好的理解我接下来所说的回溯值的求法,这里先介绍一下,如何求一个字符串的前缀和后缀相等的最大长度,为了便于说明记为k。 注意:前缀和后缀不能为字符串本身!!!!!! 如字符串“abcab”的k为2、字符串“a”的k为0、“aaaaa”的k为4、“abcaabc”的k为3。 回溯值 在主串T中寻找模式串P的过程称为模式匹配。若...

我是没有梦想的小白 1万+

ABB机器人与西门子PLC、工业相机联合实现无序抓取的完整调试方案

将此方案导入系统后,逐步执行调试,确保各环节信号正常触发,即可实现高效无序抓取!

CHUXUEZHE8210的博客 1991

rk3576 适配摄像头 (mipi 五摄)

在RK3576上实现五路CSI摄像头方案,核心思路是充分复用其视频输入接口,并通过巧妙的软件配置来实现。

weixin_35723192的博客 178

#07 串

参考答案看底部 1.求改进的失败函数nextval[j] 题目描述 在KMP算法中,进行模式匹配,在匹配失败时,主串的位置i不回溯,模式串需要根据改进的失败函数nextval[j]的值,j转移到nextval[j]位置继续进行比较。试设计函数求模式串的改进的失败函数nextval[j]。 输入描述 输入模式串 输出描述 输出模式串的改进的失败函数nextval[j] 样例输入 aaaaab 样例输出 -1-1-1-1-14 2. 求模式串的失败函数next[j] 题目描述 在KMP算法中,进行模式匹配,.

挖洞的杰瑞的博客 1245

⑩电子产品拆解分析-家用无线遥控开关433Mhz

①免布线随意贴,装上就能使用解决单线开关烦恼;②遥控配对简单,无线通讯距离长,信号可穿墙;

a6662580的博客 4683

KMP 算法详解

KMP算法是一种高效的字符串匹配算法,算法名称取自于三位共同发明人名字的首字母组合。该算法的主要使用场景就是在字符串(也叫主串)中的模式串(也叫子串)定位问题,常见的有“求子串出现的起始位置”、“求子串的出现次数”等。

这里是阿安的博客 5万+

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

详解kmp算法

1.朴素模式匹配 1.1基本思想: 从主串test 和子串pattern 的第一个字符开始,将两字符串的字符一一比对,如果出现某个字符不匹配,主串回溯到第二个字符,子串回溯到第一个字符再进行一一比对。如果出现某个字符不匹配,主串回溯到第三个字符,子串回溯到第一个字符再进行一一比对…循环一直到子串字符全部匹配成功。 1.2例如: 第一次:不匹配 第二次:主串从第2个字符,模式串从头开始,直到b与c不匹配 第三次:主串从第3个位置开始,模式串从头开始,a与c...

qq_51950769的博客 7346

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

KMP算法详解,涵盖你对kmp算法所有的不解之处

KMP算法详解,对于和我一样刚开始对KMP不理解的同学一定大有帮助!

naititi的博客 1174

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

kmp算法动图详解-中

书接上回,上次我们讲了kmp算法匹配串前缀表(next)回溯的原理,但是理解了这些可能还是无法使用kmp算法去解字符串匹配类问题,之前我们都是人工计算next表,但是代码怎么计算出前缀表呢,这又是个头疼的问题。下面我们还是结合动图来讲。is[i]ijj1、当s[i]==s[j]时,我们后移i和j,且2、当遇到s[i]!=s[j],为了方便观察,我们将原本的数组复制一份,分别标注i和j的位置,ijjijjij3、此时只需要继续判断s[i]和s[j]是否相等,重复步骤一和步骤二即可得到next数组。

u014018190的专栏 705
上一篇: 字典树算法详解
下一篇: UNILM翻译
yphacker
博客等级 码龄12年 199粉丝 540原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值