【详解】KMP算法——多图,多例子(c语言)

leetcode 028.实现strStr(),即查找重复字符串(KMP算法) 前言 本题是经典的字符串单模匹配的模型,因此可以使用字符串匹配算法解决,常见的字符串匹配算法包括暴力匹配、Knuth-Morris-Pratt 算法、Boyer-Moore 算法、Sunday 算法等,本文 ## 前言 本题是经典的字符串单模匹配的模型,因此可以使用字符串匹配算法解决,常见的字符串匹配算法包括暴力匹配、Knuth-Morris-Pratt 算法、Boyer-Moore 算法、Sunday 算法等,本文将讲解朴素解法(暴力匹配)和KMP算法 因为哈希方法可能出现哈希值相等但是字符串不相等的情况 阅读详情
AI摘要

本文深入浅出地介绍了KMP算法的原理与应用,通过大量实例和图表解释了如何避免传统字符串搜索中的多余回溯,详细解析了Next数组的计算方法,并提供了完整的C语言实现代码。

目录

前言

1.KMP算法是什么?

2.为什么需要KMP算法?

2.1主串找字串

2.2暴力求解

3.KMP准备工作

3.1字符串的前后子串

3.2最大前后相等子串

3.3最大前后相等子串练习

4.KMP算法

4.1简看KMP算法

5 Next数组     

5.1j该回溯的位置

 5.2学会计算Next数组           

5.3用数学表示next数组(重点)

5.3.1arr2[k] == arr2[j]

5.3.2 arr2[k] != arr2[j]

5.3.3 k回溯到尽头

6.代码实现KMP

6.1KMP外壳

6.2KMP内核

6.3KMP全部代码

7.结语


前言

KMP算法作为程序员的必修课之一,其抽象的过程让初学者叫苦不迭,但是当你完全理解过后会发现其中蕴含着创造者的无穷智慧。本篇文章我将以大量的例子与图片,为你讲解这个奇妙的算法。


1.KMP算法是什么?

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



 。(来自百度百科)

简而言之就是:减少在主串找子串的过程中回退的次数。(先有个概念就行,后面会仔细讲解)


2.为什么需要KMP算法?

在回答这个问题前我们需要知道先知道两个问题。

什么叫主串找子串?

不用kmp算法,直接暴力求解是怎样的?

2.1主串找字串

现在我们有主串:arr1[] = "abababc",子串:arr2[] = “abc”。那么我们在arr1中找到arr2在其中位置的过程就叫做主串找子串。

2.2暴力求解

在暴力求解中,我们是将子串和主串逐一匹配,如果第一个字符相等就继续匹配第二个字符,直到子串与主串全都匹配成功,就返回子串的位置,一旦其中某两个字符匹配不成功,主串就回到开始匹配字符的下一字符,而子串回到第一字符。

上面的话可能有一点绕,那么看了下面的图片你就会明白暴力求解的思路。

还是这俩字符串,主串:arr1[] = "abababc",子串:arr2[] = “abc”。

(1) 第一次匹配成功,第二次匹配成功,第三次匹配不成功。

              

 (2) 前面匹配失败,第一个字符串回到第二个字符'b',第二个字符串回到第一个字符'a'处。

           第一次匹配失败。

           

(3) 前面匹配失败,第一个字符串回到第三个字符'a',第二个字符串回到第一个字符'a'处。

          第一次匹配成功,第二次匹配成功,第三次匹配不成功。

             

(4) 前面匹配失败,第一个字符串回到第四个字符'b',第二个字符串回到第一个字符'a'处。

          第一次匹配失败。

               

(5) 前面匹配失败,第一个字符串回到第五个字符'a',第二个字符串回到第一个字符'a'处。

          第一次匹配成功,第二次匹配成功,第三次匹配成功,子串走到尽头,成功找到在第一字符            串找到第二字符串。

                  

通过以上举例可以看出,传统的暴力求解,需要多次回溯,且第一个字符串和第二个字符串都需要回溯,而且例如(2)(4)步,明显回溯过去也一定是错的,那有没有什么办法让他回溯到特定的位置,不至于像暴力求解一样,产生许多不必要的步骤,于是就有了本篇的重点:

                                                               KMP算法!!!


3.KMP准备工作

在学习KMP算法之前我们还需要进行一些小小的的准备。这对你掌握KMP算法是非常必要的。

3.1字符串的前后子串

先抛开找字符串的问题,抛开什么KMP算法,我们来了解一下什么叫一个字符串的前后相等子串。

--假设有这样一个字符串:a[] = "abcabcabc";

那么他的前子串的集合为:{"a","ab","abc","abca","abcab","abcabc","abcabca","abcabcab"}

看不懂?上图!图片顺序是从左向右哦!(注:作者懒,字符串的\0我没画😉)

--知道了什么叫前子串,那么字符的后子串也很好理解了。

他的后子串的集合为:{"c","bc","abc","cabc","bcabc","abcabc","cabcabc","bcabcabc"}

3.2最大前后相等子串

我们现在已经知道了字符串a[] = "abcabcabc"的两个信息:

前子串的集合为:{"a","ab","abc","abca","abcab","abcabc","abcabca","abcabcab"}

后子串的集合为:{"c","bc","abc","cabc","bcabc","abcabc","cabcabc","bcabcabc"}

很明显就可以看出前后两个子串相等的有{"abc","abcabc"};

那最大前后相等子串就是"abcabc",其长度为6。

3.3最大前后相等子串练习

kmp算法的准备工作已经完成,如果你还是有点不太清楚,这里有几个字符串,你不妨可以试着找出他们的最大前后相等子串,以及长度,来加深你对前面内容的的理解。

        a[] = "abcdefgh"                         b[] = "abcabcabcabcabc"        c[] = "aba"

        d[] = "hello world"                       e[] = "ababcabcdabcde"          f[] = "abcabcdeabcabcde"

 答案:

a[]:没有最大前后相等子串    0
b[]:"abcabcabcabc"         12
c[]:"a"                    1
d[]:没有最大前后相等子串    0
e[]:没有最大前后相等子串    0
f[]:"abcabcde"             8

4.KMP算法

4.1简看KMP算法

前面我们多次强调过,kmp算法只需要子串返回到特定位置,而主串不用返回。

这到底是一个怎样的过程呢?

还是这俩字符串,主串:arr1[] = "abababc",子串:arr2[] = “abc”。

绿色是回溯的位置,红色是匹配结束的位置。

(1)第一次匹配成功,第二次匹配成功,第三次匹配失败。

KMP算法详解-彻底清楚了(转载+部分原创) KMP算法详解-彻底清楚了(转载+部分原创) 引言 KMP算法指的是字符串模式匹配算法,问题是:在主串T中找到第一次出现完整子串P时的起始位置。该算法是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的,以其名字首字母命名。在网上看了不少对KMP算法的解析,大多写的不甚明了。直到我看到一篇博客的介绍,看完基本了解... 阅读详情

相关推荐

KMP算法C语言实现,完整代码

#include <stdio.h> #include <string.h> void get_next(char s[],int next[]); int KMP(char s1[],char s2[],int next[]); int main() { int i= 0; int next[1000]; char s2[] = "abcac"; char s1[] = "ababcabcacbab"; get_next(s2,next); i=KMP(s1,

wangchengjiea的博客 1万+

KMP算法详解与C语言实现

1.什么是KMP算法 KMP算法是一种字符串匹配算法,即在主字符串查找模式字符串(简单来说就是判断一个字符串中是否包含另一个字符串),是C语言库函数strstr的算法优化。 2.通常情况下的字符串匹配 首先来讲一讲不用KMP算法的字符串匹配,便于理解之后KMP算法,和KMP算法的优势。 首先建立一个字符串作为主串: char a[]="abcbabc"; 这个字符串在内存中是这样存放的: 假设现在要在这个字符串中查找字符串"ba"。即我们也要定义一个数组来放"bca"。b[2]="bc.

分享学习的知识,记录我的技术成长道路 2888

数据结构与算法 | KMP算法及其改进算法的核心思路 (C语言实现)

kmp算法是子串配对的一种,并不是速度最快的,但是其算法思想非常巧妙。请允许我尝试用白话描述一下其思想,如果有什么不对的地方,恳请矫正。

峰峰的博客 2943

KMP算法C语言

KMP算法是一种改进的字符匹配算法,具体实现是通过构造next数组,通过next数组指示下一轮应用于进行匹配的元素位置减少了模式串与主串的匹配次数,优化了算法的时间复杂度。S串 主串T串 模式匹配串next数组的建立原理建立一个字符串数组,字符串数组的第一个元素a[0]规定用存放数组中含有的字符个数。比如主串S为abaabaaab,则s[0] = 9,s[1] = 'a',s[2] = 'b',s...

Hello World.c 1202

保姆级教程:用Unity为麒麟系统打包Linux应用(含路径权限全攻略)

本文提供了一份详细的Unity跨平台开发指南,重点介绍如何在麒麟系统上打包和部署Linux应用。从开发环境配置、路径权限处理到性能优化和常见问题解决,全面解析了Unity项目在国产操作系统上的适配流程,帮助开发者高效完成跨平台应用开发。

weixin_28692867的博客 506

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印

ProceduralMan的博客 7410

在MacBook上直接跑Windows Server 2022:一个开发者的真实踩坑与配置全记录

本文详细记录了在MacBook上原生运行Windows Server 2022的完整流程与优化技巧。通过Boot Camp实现非虚拟机安装,开发者可以充分利用Mac硬件性能,搭建高效的本地开发环境,特别适合需要测试跨平台应用和服务器功能的场景。文章涵盖驱动处理、分区策略、Docker配置等关键步骤,为技术极客提供实用指南。

weixin_42620913的博客 247

路径规划 | 图解A*、Dijkstra、GBFS算法的异同(附C++/Python/Matlab仿真)

图解A*、Dijkstra、GBFS算法原理,分析三种算法异同,提供C++/Python/Matlab仿真实现

FRIGIDWINTER的博客 2万+

SAP Build Work Zone standard edition 订阅报错 OIDC trust missing 的成因与完整解决路径

摘要:用户订阅SAP Build Work Zone时遇到422错误,提示未配置OpenID Connect信任。该错误表明业务用户需通过SAP Cloud Identity Services的OIDC协议认证,而当前子账户仅配置了SAML信任或未配置信任。解决方法是进入子账户的Trust Configuration页面,使用Establish Trust功能建立与SAP Cloud Identity Services的OIDC信任关系。这是SAP新版服务的强制要求,SAML协议已不被支持。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 197

RK3568平台(KBuild篇)KBuild编译体系

从Linux内核2.6开始,Linux内核的编译采用Kbuild系统,这和过去的编译系统有很大的不同,尤其对于Linux内核模块的编译。在新的系统下,Linux编译系统会两次扫描Linux的Makefile:首先编译系统会读取Linux内核顶层的Makefile,然后根据读到的内容第二次读取Kbuild的Makefile来编译Linux内核。kbuild,即 kernel build,用于编译 Linux 内核文件。

weixin_49303682的博客 349

SAP_MM模块采购订单显示含税价&不含税简介

不含税价(Net Price):基础商品价格,不包含税金。含税价(Gross Price):基础价格加上适用税金后的总价。在SAP中,采购订单通常以不含税价为基础,通过配置税码和定价方案,系统会自动计算含税总价。

我小时候很黑的博客 2303

WPS文档中心和文档中台 operate 未授权访问漏洞(CVE-2025-0717)

WPS文档中心和文档中台的/open/v6/api/etcd/operate?key=/config/storage&method=get接口存在未授权访问漏洞,攻击者可通过该漏洞获取AK/SK密钥等信息,这些密钥通常用于系统内部认证和权限控制,泄露后可能导致攻击者进一步修改K8s配置、部署恶意容器或执行远程命令,最终实现对系统的完全控制。

李同學AI安全 905

Statistics and Machine Learning Toolbox

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

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

上一篇: 【咬文嚼字】c语言中你可能不知道的小知识
下一篇: 【咬文嚼字】c语言中你可能不知道的小知识(2)
Raizeroko
博客等级 码龄6年 1913粉丝 27原创
评论 48
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值