KMP算法详解

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

问题描述

指定文本串:aabaabaaf和模式串:aabaaf

使用KMP算法判断模式串是否在文本串中出现过?

假定模式串的长度小于文本串

思路解析

BF算法的问题是:模式串已经匹配到最后一位了发现不一样,需要将文本串和模式串的指针都往后退,导致有很多的重复匹配,效率很低。

KMP算法的思路是,在发现某个字符不匹配的时候,充分利用前面已经匹配过的结果,不要把“搜索指针”回退到已经比较过的位置,而是把模式串往后移动到合适的位置继续比较。KMP算法只需要对文本串搜索一次,时间复杂度是O(n)。

检索过程图解

如上图所示,在遇到不匹配的时候,依靠“部分匹配表”可知,最后一个匹配字符a对应的部分匹配值是2,可以根据下面的公式计算出模式串的移动位数。

移动位数 = 已经匹配的字符串长度 - 对应的部分匹配值

aabaa是已经匹配的字符串,长度是5;aabaa对应的部分匹配值是2,因此将模式串往右移动3位,就可以继续匹配了,KMP就是通过这个“部分匹配表”避免了搜索指针的回退。

部分匹配表

要理解部分匹配表,需要了解两个概念:前缀子串、后缀子串

  • 前缀子串:包含首字母,不包含尾字母的所有子串

  • 后缀子串:包含尾字母,不包含首字母的所有子串

例如:单词"bread"

  • 前缀子串:"b","br","bre","brea"

  • 后缀子串:"d","ad","ead","read"

部分匹配表中的数值含义是:当前这个字符前面的字符串中,相等的前缀子串和后缀子串的最大的长度。计算下aabaa的部分匹配表:

  • a:前缀子串集合和后缀子串集合都是空集,相等的前后缀子串的最大长度是0

  • aa:前缀子串集合是[a],后缀子串集合是[a],相等的前后缀子串的最大长度是1

  • aab:前缀子串集合是[a,aa],后缀子串集合是[b,ab],相等的前后缀子串的最大长度是0

  • aaba,前缀子串集合是[a,aa,aab],后缀子串集合是[a,ba,aba],相等的前后缀子串的最大长度是1

  • aabaa,前缀子串集合是[a,aa,aab,aaba],后缀子串集合是[a,aa,baa,abaa],相等的前后缀子串的最大长度是2

  • aabaaf,前缀子串集合是[a,aa,aab,aaba,aabaa],后缀子串集合是[f,af,aaf,baaf,abaaf],相等的前后缀子串的最大长度是0

“部分匹配表”的实质是,模式字符串中有时会有重复的子串,例如:aabaa的左右两边都有aa,那么该字符串的部分匹配值就是2,那么在发现aabaaf中的f不匹配的时候,只需要将aabaaf这个模式串往右移动3个位置,就可以让第一个aa来到第二个aa的位置。

代码实现

package org.javaadu.string;

import java.util.List;

publicclassStringSearchDemo{

    publicstaticvoidmain(String[] args){
        String text = "aabaabaaf";
        String pattern = "aabaaf";

        boolean kmpRes = kmpSearch(text, pattern);
        System.out.println("kmpRes:" + kmpRes);
    }

    /**
     * 利用KMP算法求解pattern是否在text中出现过
     *
     * @param text    文本串
     * @param pattern 模式串
     * @return pattern在text中出现,则返回true,否则返回false
     */publicstaticbooleankmpSearch(String text, String pattern){
        //部分匹配数组,就是很多算法实现中的next数组int[] partMatchTable = buildPartMatchTable(pattern);
        //text中的指针int i = 0;
        //pattern中的指针int j = 0;

        while (i < text.length()) {
            if (text.charAt(i) == pattern.charAt(j)) {
                //字符匹配,则两个指针同时后移
                i++;
                j++;
            } elseif (j > 0) {
                //字符失配,则利用next数组,异动j指针,避免i指针回退
                j = partMatchTable[j - 1];
            } else {
                //pattern中的第一个字符就失配了
                i++;
            }

            if (j == pattern.length()) {
                //搜索成功returntrue;
            }
        }
        returnfalse;
    }

    privatestaticint[] buildPartMatchTable(String pattern) {
        //初始化int[] partMatchTable = newint[pattern.length()];
        int prefixLen = 0;
        next[0] = 0;
        int i = 1;

        while (i < pattern.length()) {
            //pattern[prefixLen],表示目前最长相等子串的最后一位//pattern[i],表示目前正在处理的子串的最后一位的字符if (pattern.charAt(prefixLen) == pattern.charAt(i)) {
                //如果它俩相等,说明找到了更长的相等子串
                prefixLen++;

                partMatchTable[i] = prefixLen;
                i++;//处理下一个i的字符
            } else {
                //如果不相等,则需要尝试下更短1位的子串是否满足要求,因此这里要把再次循环尝试下:仅仅改变prefixLen的值,不改变i的值
                prefixLen = next[prefixLen - 1];
                if (prefixLen == 0) {
                    //如果实在没有合适的,则说明当前正在处理的子串的最长相等前后缀的长度是0
                    partMatchTable[i] = 0;
                    i++;//处理下一个i的字符
                }
            }
        }
        return partMatchTable;
    }
}
3D深度饼图的QT实现 首先,我们需要创建一个QT项目并创建一个窗口,用于显示我们的饼图。在QT Creator中,选择创建一个新的QT Widgets应用程序项目,并创建一个新的窗口类。在本文中,我将介绍如何使用QT实现一个3D深度饼图(Pie 3D)的可视化效果。在构造函数中,我们将创建一个饼图(QChartView)并设置饼图的数据。这是一个简单的示例,您可以根据需要自定义和扩展代码来创建更复杂的饼图。现在,我们已经完成了3D深度饼图的QT实现。您将看到一个具有相应数据的3D深度饼图显示在窗口中。3D深度饼图的QT实现。 阅读详情

相关推荐

【STM32】433MHz OOK信号软解码实战:从EV1527协议到嵌入式实现

本文详细介绍了基于STM32微控制器实现433MHz OOK信号软解码的完整实战过程。文章从EV1527协议解析入手,重点阐述了利用STM32的GPIO和定时器进行信号采样、脉宽还原、同步头识别以及数据位判决的核心算法,并提供了对抗无线干扰的容错优化策略,帮助开发者深入理解并掌握低成本无线通信的嵌入式实现方案。

weixin_29299807的博客 786

串的模式匹配——Brute-Force与KMP算法

Brute-Force算法 Brute-Force算法简称BF算法,也叫简单匹配算法或暴力匹配算法,采用穷举法,其基本思想为:从目标串str="aabaabaaf"的第一个字符开始和模式串substr="aabaaf"中的第一个字符相比较。若相等,则继续逐个比较后续字符;否则从目标串str的第二个字符开始重新与模式串substr中的第一个字符比较。以此类推,若从目标串str的第i个字符开始,每个字符依次与模式串substr中的对应字符相等,则匹配成功,该算法返回位置i——表示此时substr的第一个字符在

cdypa的博客 709

从问卷到结论:手把手教你用SPSS 28完成一份完整的社科数据分析报告

本文详细介绍了如何使用SPSS 28完成社会科学研究中的数据分析报告,从问卷数据导入、清洗到描述性和推断性统计分析,再到结果呈现与报告撰写。通过实际案例演示,帮助研究者掌握SPSS 28的核心功能,提升数据分析效率与报告质量。

weixin_28717431的博客 249

【算法】kmp

是由发明这个算法的三个科学家的名称首字母组成。

橙子的博客 591

8.Python基础语法(五)续【光说不练假把式,上题】

Python基础语法(二) 有关于Python循环语句的几道实操,让大家理解知识点更深更透彻~

孤寒者的博客 2万+

【云原生】Docker可视化工具Portainer使用详解

Docker可视化工具Portainer使用详解

congge 1万+

KMP算法

本文章基于carl大佬的视频讲解所整理出来的kmp算法笔记,原视频在这里帮你把KMP算法学个通透!(理论篇) 解决的问题 KMP解决的就是字符串匹配的问题,例如: 文本串:aabaabaaf 模式串:aabaaf 目的,是为了求证在文本串当中是否有模式串的出现 KMP算法流程: 首先按照上面的例子,模式串和文本串先一一对应的进行匹配,在模式串遍历到 f 的时候,文本串遍历到了 b,此时 f 和 b 不匹配,这时候KMP算法会找模式串中不匹配地方 f 前面的字符串当中的最长相等前后缀的下标。这里 f 前面的字

Mr_Carrot的博客 1047

什么是DHCP Snooping?如何配置DHCP Snooping?

功能描述防护类型防御伪造 DHCP 服务器、避免地址冲突、增强网络安全性使用场景企业园区网、校园网、大型局域网配合机制IP Source Guard、DAI、防止 ARP 欺骗部署难度⭐⭐(简单)“DHCP Snooping,是内网 DHCP 安全防护的第一道门神。” 🛡️。

网络技术联盟站 1267

41、【匹配算法】KMP字符串匹配算法(C/C++版)

一、介绍 KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。 二、所解决的问题 解决字符串的匹配问题,即所谓模式匹配,可理解为在目标(字符串)中寻找一个给定的模式(也是字符串),返回目标和模式匹配的第一个子串的首字符位置。通常目标串比较大,而模式串则比较短小。 最简单的实现方法是暴力法,进行依次对比遍历,时间复杂度为O(n^2)。根据字符串自身中具有相同这一性质,可对其进行优化,设计了KMP

STAR GAME 1774

第十二章 供水管网水力模型软件介绍

本文介绍了国内外主要供水管网建模软件及其特点,重点分析了某高建模软件V14的创新功能。国际主流软件包括开源的EPANET、商业软件InfoWorksWS、WaterGEMS和MIKEURBAN,各具特色但存在应用局限。某高V14软件实现了管网GIS与模型一体化管理,采用一G多网、一网多模、一模多案、网模合一技术路线,支持全信息模型建立和动态数据更新。其创新点包括水量分配理念革新(精确/模糊匹配、三种用水模式)和首创Web服务功能。通过并发计算、GPU加速等技术优化性能,具有较高性价比。

weixin_45258875的博客 210

49、非合作目标运动参数估计与状态滤波方法研究

本文研究了非合作空间目标的运动参数估计与状态滤波方法。通过分析目标的章动运动特性,建立了运动方程,并分别提出了基于最小二乘法的质心运动参数估计方法和旋转运动参数估计方法。同时,设计了误差状态卡尔曼滤波器(ESKF)用于姿态滤波和角速度估计,以提高估计精度。仿真实验验证了所提方法的有效性,能够准确估计目标的运动参数和状态信息,为在轨服务提供了技术支持。

gpt4scribbler的博客 91

KMP 算法详解

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

这里是阿安的博客 5万+

【vsomeip3 教程】SOME/IP中间件去抖策略全解析

本文探讨了在SOME/IP中间件中实现Debounce(去抖动)机制的必要性和实现原理。文章首先分析了中间件层进行Debounce的四大动机:多订阅者共享收益、语义显式化、协议噪声屏蔽和入口处背压控制。接着详细阐述了Debounce的底层原理,包括变化检测机制(ignore和mask的应用)、时间门控策略(interval的两种时间基准)以及超时补发机制,并通过表格清晰展示了不同参数组合的效果和适用场景。最后,文章提出了工程落地的具体方法,包括策略选型、ignore/mask的设计方法论以及分层验证调试的实

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 232

详解kmp算法

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

qq_51950769的博客 7347

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Statistics and Machine Learning Toolbox

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

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

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

naititi的博客 1174

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: Alibaba之MySQL宝典流出!极致经典,堪称行业天花板
下一篇: 【首页推荐】阿里大佬带你一个月刷完Java高频面试八股文,比啃书效果好多了...
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值