KMP匹配算法概念+实例

【详解】KMP算法——多图,多例子(c语言) 前言 KMP算法作为程序员的必修课之一,其抽象的过程让初学者叫苦不迭,但是当你完全理解过后会发现其中蕴含着创造者的无穷智慧。本篇文章我将以大量的例子与图片,为你讲解这个奇妙的算法。 KMP算法是什么? KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函 阅读详情

此文重点梳理两种最常见的next数组,以及在KMP匹配中的应用

符号说明

模式串:T[i]i=1,...,T_length主串:S[i]i=1,...,S_lengthnext数组:next[i]i=1,...,T_length 模式串:T[i] \quad i=1,...,T\_length\\ 主串:S[i] \quad i=1,...,S\_length\\ next数组:next[i]\quad i=1,...,T\_length\\ 模式串:T[i]i=1,...,T_length主串:S[i]i=1,...,S_lengthnext数组:next[i]i=1,...,T_length

第一种next数组

第一种next数组在KMP中的作用为:
当S[i]与T[j]在主串 S[i]S[i]S[i] 处匹配失败时,将指向模式串的指针 jjj 跳转到模式串的 next[j]next[j]next[j]处
next[j]={0当j=1时Max{k∣1<k<j且“T1⋯Tk−1”=“Tj−k−1⋯Tj−1”}当此集合不为空时1其他情况 next[j]=\begin{cases} 0 &当j=1时\\ Max\{k|1<k<j且“T_1 \cdots T_{k-1}”=“T_{j-k-1}\cdots T_{j-1}”\} &当此集合不为空时\\ 1 &其他情况\\ \end{cases} next[j]=⎩⎨⎧​0Max{k∣1<k<j且“T1​⋯Tk−1​”=“Tj−k−1​⋯Tj−1​”}1​当j=1时当此集合不为空时其他情况​
例1.T="aba"时next数组的计算过程

例2.T="abaabcac"时next数组的计算过程
由于aba在上例中已计算过,从j=4开始

通过两个例子,可以将next数组的公式总结为:

  1. j=1时,nextj]=0成立
  2. 当j ≠\neq= 1时,扫描1~j-1,得到最长前后缀长度;next[j]=最长前后缀长度+1
    (若无相等,则前后缀长度为0,next[j]=1。如例2中j=7时)
    注意:前缀和后缀可重叠

练习1.
求abababaab的next数组

011234562

代码实现

void get_next(int T_length) {//模式串next数组的生成
	int i = 1, j = 0;
	next[1] = 0;
	while (i <= T_length) {
		if (j == 0 || T[i] == T[j]) {
			i++;
			j++;
			next[i] = j;
		} else
			j = next[j];
	}
}

在KMP中的应用

int  Index_KMP(int S_length, int T_length, int pos) {//从pos开始的一次KMP匹配
	int i = pos, j = 1;
	while (i <= S_length && j <= T_length) {
		if (j == 0 || S[i] == T[j]) {
			i++;
			j++;
		} else
			j = next[j];
	}
	if (j > T_length) {
		printf("%d ", i - T_length);
		return i - T_length;
	} else return 0;//若匹配失败
}

第二种next数组

第一中next数组在KMP中的作用为:
当S[i]与T[j]匹配失败时,查询前一位 j-1 的next[j-1],跳过next[j-1]个数,从next[j-1]+1的位置开始重新匹配。
next[j]={0当j=1时Max{k∣1<k<j且“T1⋯Tk”=“Tj−k+1⋯Tj”}当此集合不为空时0其他情况 next[j]=\begin{cases} 0 &当j=1时\\ Max\{k|1<k<j且“T_1 \cdots T_{k}”=“T_{j-k+1}\cdots T_{j}”\} &当此集合不为空时\\ 0&其他情况\\ \end{cases} next[j]=⎩⎨⎧​0Max{k∣1<k<j且“T1​⋯Tk​”=“Tj−k+1​⋯Tj​”}0​当j=1时当此集合不为空时其他情况​
例3.T="aba"时next数组的计算过程

例4.T="abaabcac"时next数组的计算过程
由于aba在上例中已计算过,从j=4开始

通过两个例子,可以将next数组的公式总结为:
  1. j=1时,nextj]=0成立
  2. 当j ≠\neq= 1时,扫描1~j,得到最长前后缀长度;next[j]=最长前后缀长度
    (若无相等,则前后缀长度为0,next[j]=0。如例4中j=7时)

代码实现

void get_next(int T_length) {//模式串next数组的生成
	int i = 2, j = 1;
	next[1] = 0;
	while (i <= T_length) {
		if(j==1&&T[i]!=T[j]){
			next[i]=0;
			i++;
		}
		if ( T[i] == T[j]) {
			next[i] = j;
			i++;
			j++;
		} else {
			j = next[j-1] + 1;
		}
	}
}

在KMP中的应用

int  Index_KMP(int S_length, int T_length, int pos) {//从pos开始的一次KMP匹配
	int i = pos, j = 1;
	while (i <= S_length && j <= T_length) {
		if(j==1&&S[i]!=T[j]){
			i++;
		}
		if (S[i] == T[j]) {
			i++;
			j++;
		} else {
			j = next[j-1] + 1;
		}
	}
	if (j > T_length) {
		printf("%d ", i - T_length - 1);
		return i - T_length;
	} else return 0;//若匹配失败
}

完整实现:
一:

#include<bits\stdc++.h>
#define MaxSize 10000
char T[MaxSize], S[MaxSize];
int next[MaxSize];
void get_next(int T_length) {//模式串next数组的生成
	int i = 1, j = 0;
	next[1] = 0;
	while (i <= T_length) {
		if (j == 0 || T[i] == T[j]) {
			i++;
			j++;
			next[i] = j;
		} else
			j = next[j];
	}
}
int  Index_KMP(int S_length, int T_length, int pos) {//从pos开始的一次KMP匹配
	int i = pos, j = 1;
	while (i <= S_length && j <= T_length) {
		if (j == 0 || S[i] == T[j]) {
			i++;
			j++;
		} else
			j = next[j];
	}
	if (j > T_length) {
		printf("%d ", i - T_length);
		return i - T_length;
	} else return 0;//若匹配失败
}
int main() {
	int i;
	int S_length ;//主串
	int T_length ;//模式串
	
	scanf("%d", &T_length);
	scanf("%s", T + 1);
	scanf("%d", &S_length);
	scanf("%s", S + 1);

	get_next(T_length);

	for (int position = 1; position < S_length; position++ ) {
		position = Index_KMP(S_length, T_length, position);
		if (position == 0)
			break;
	}
	/*for (i = 1; i <= T_length-1; i++)//输出next数组
		printf("%d ", next[i]);
	printf("%d", next[i]);*/
	return 0;
}

二:

#include<bits\stdc++.h>
#define MaxSize 10000
char T[MaxSize], S[MaxSize];
int next[MaxSize];
void get_next(int T_length) {//模式串next数组的生成
	int i = 2, j = 1;
	next[1] = 0;
	while (i <= T_length) {
		if(j==1&&T[i]!=T[j]){
			next[i]=0;
			i++;
		}
		if ( T[i] == T[j]) {
			next[i] = j;
			i++;
			j++;
		} else {
			j = next[j-1] + 1;
		}
	}
}
int  Index_KMP(int S_length, int T_length, int pos) {//从pos开始的一次KMP匹配
	int i = pos, j = 1;
	while (i <= S_length && j <= T_length) {
		if(j==1&&S[i]!=T[j]){
			i++;
		}
		if (S[i] == T[j]) {
			i++;
			j++;
		} else {
			j = next[j-1] + 1;
		}
	}
	if (j > T_length) {
		printf("%d ", i - T_length - 1);
		return i - T_length;
	} else return 0;//若匹配失败
}
int main() {
	int i;
	int S_length ;//主串
	int T_length ;//模式串

	scanf("%d", &T_length);
	scanf("%s", T + 1);
	scanf("%d", &S_length);
	scanf("%s", S + 1);

	get_next(T_length);

	for (int position = 1; position < S_length; position++ ) {
		position = Index_KMP(S_length, T_length, position);
		if (position == 0)
			break;
	}
	/*printf("\n");
	for (i = 1; i <= T_length - 1; i++) //输出next数组
		printf("%d ", next[i]);
	printf("%d", next[i]);*/
	return 0;
}
KMP算法及相关例题整理(未完待续) 目录: 一、KMP算法 二、例题及代码编写指导 三、模板 一、KMP算法 在计算机科学中,KMP 算法(Knuth–Morris–Pratt string-searching algorithm)是用于搜索在一个字符串中某个字串的出现次数的算法,该算法考察:在失配发生时,应该在何处开始匹配下一个字符,以免于重新比较先前已经匹配的字符。 这个算法在 1970 年被 Donald Knuth 和 Va... 阅读详情

相关推荐

KMP算法解决字符串匹配问题(详细步骤图解)

KMP算法图解 文章目录一、KMP算法步骤图解二、部分匹配值是怎么产生的代码 一、KMP算法 KMP是一个解决模式串在文本串中是否出现过,如果出现过,最早出现的位置的经典算法 KMP算法常用于在一个文本串S中查找一个模式串P的出现位置,这个算法在1977年由Donald Knuth、Vaughan Pratt、James H.Morris三人发表 KMP算法利用之前判断过信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算

wenwenaier的博客 6346

KMP算法详解

KMP算法详解 什么是KMP 说到KMP,先说一下KMP这个名字是怎么来的,为什么叫做KMP呢。 因为是由这三位学者发明的:Knuth,Morris和Pratt,所以取了三位学者名字的首字母。所以叫做KMP KMP有什么用 KMP主要应用在字符串匹配上。 KMP的主要思想是当出现字符串不匹配时,可以知道一部分之前已经匹配的文本内容,可以利用这些信息避免从头再去做匹配了。 所以如何记录已经匹配的文本内容,是KMP的重点,也是next数组肩负的重任。 其实KMP的代码不好理解,一些同学甚至直接把KMP代码的模板

JavaAlenboy 2730

KMP算法(字符串匹配算法)之PHP语言实现

KMP算法(模式匹配算法):该算法的关键是求出P0···Pi的最大相同前后缀长度k(部分匹配表): 首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。 "部分匹配"的实质是,有时候,字符串头部和尾部会有重复。比如,"ABCDAB"之中有两个"AB",那么它的"部分匹配值"就是2("AB"的长度)。搜索词移动的时候,第一个"AB"向后移动4位(字符串长度6 - 部分匹配值2 = 4),就可以来到第二个"

Just Do IT ! 3906

【考研】串的模式匹配算法——KMP算法(含真题)

本文内容源于对《数据结构(C语言版)》(第2版)、王道讲解学习所得心得、笔记整理和总结,以便复习。【考研】《数据结构》知识点总结.pdf_考研数据结构知识点总结-其它文档类资源-优快云文库【2023考研】数据结构常考应用典型例题(含真题)_住在阳光的心里的博客-优快云博客目录前言一、基本概念二、KMP算法三、KMP算法的进一步优化四、习题。

qq_34438969的博客 8749

C语言KMP算法与字符串朴素的模式匹配算法(暴力)编程小白必学

一、串的定义 串是由零个和多个字符组成的有限序列,又名叫字符串。一般记为 s="a1a2a3.......an"(n&gt;=0),其中s是串的名字,用双引号括起来的字符序列是串的值。串中的字符长度n称为串的长度。零个字符的串称为空串。 还有一些概念需要解释 子串与主串:串中任意个数的连续字符组成的子序列称为该串的子串,相应地,包含子串的串称为主串。子串在主串中的位置就是字串的第一个字符在...

weixin_43977523的博客 1168

Playwright Java环境配置避坑指南:浏览器路径、类加载与离线部署

Playwright作为现代端到端测试框架,其Java SDK突破了传统Selenium的Driver管理模式,将Chromium/Firefox/WebKit内核视为可编程运行时资源。其核心原理在于SDK与浏览器二进制分离——Maven仅管理Java字节码,而浏览器需独立下载、校验与沙箱加载。这一设计带来显著技术价值:跨平台一致性、进程隔离安全性及多浏览器并行能力;典型应用场景涵盖Spring Boot集成测试、金融级离线CI/CD、Kubernetes容器化部署及Air-Gapped封闭环境。然而,因J

weixin_32956805的博客 675

字符串匹配(KMP 算法 含代码)

串(string或字符串)是由零个或多个字符组成的有限序列,一般记为 其中s是串的名,用单引号括起来的字符序列是串的值;ai(1 串中任意个连续的字符组成的子序列称为该串的子串。包含子串的串相应的称为主串。通常称字符在序列中的序号为该字符在串中的位置。子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。 下面主要说一下串的模式匹配算法 传统的串匹配法 算法的基本思想是:从主串

梦里水乡的专栏 5354

从零开始的BW(五) 外部系统供数之OData测试

5、激活添加的服务,如提示下图中的激活失败,根据生成URI在事务代码SICF目录中找到对应的服务,设置超时时间,设置完之后重新激活即可,详情可参考SAP note 1986626。如果刚才设置BY Odata的query在这没有显示,SE38执行程序EQ_RS_AUTOSETUP,选中需要生成服务的query,生成服务后再去添加服务。测试get方法,URI中默认的参数是?4、事务代码/IWFND/MAINT_SERVICE中添加服务,如果提示用户不再登陆,在事务代码前加上/O或者/N即可。

m0_61386064的博客 1107

字符串匹配 --- BF算法 && KMP算法

对于此时不匹配我们能提取到的一个信息是你其实知道前面六个字符是"ABCDAB",因此我们可以利用这个信息找到最大程度能匹配子串的一部分,此时就是最好的情况这便是KMP算法的核心 --- 利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。与BF算法不同的是,当匹配失败时,主串时不回退的,子串回退到相应位置。问题是KMP算法中,当匹配失败时,子串怎么知道该回退到哪个位置?

2301_79448270的博客 1156

Openclaw 附录B 常用Skills清单

核心作用支持URL、网页、PDF、图片、音频和YouTube视频的摘要与字幕提取,由OpenClaw创始人@steipete开发的官方内置Skill。安装⚠️说明:原推荐的summarize未在ClawHub验证到,YouTube字幕提取功能已内置于summarize中。使用场景“提取这个2小时Next.js教程视频的核心代码逻辑,按章节整理成学习笔记”推荐指数:⭐⭐⭐⭐。

Maynor的博客 857

传统(经典)粒子群算法(PSO)解决单目标优化问题

智能算法:粒子群算法(particle swarm optimizer)—PSO %原理:(1)种群初始化–N(种群数)–D(个体数)–x(i)(粒子位置)–v(i)(粒子速度) % (2)计算每个粒子的适应度值–而适应度值需要选择适应度函数 % (3)对于每个粒子,使用它的适应度值fit[i]和个体的极值pbest(i)进行比较,如果fit[i]>pbest(i),则pbest(i)=fit[i] % (4)同理,对每个粒子用它的适应值与全局极值进行比较,如果比它大,则

weixin_51631044的博客 1295

KMP算法——字符串快速匹配

快速匹配模式串,KMP YES!

My vegetable has exploded. 3045

YOLOv12 改进 | Backbone改进 3

将CSP中的简单拼接改为可学习的特征选择门控,动态决定哪些特征流向下一层,同样再写这篇。:相比静态CSP的固定50/50分割,门控机制可学习0.3:0.7等最优比例。在输入端加入轻量SR模块,对下采样后的特征进行超分恢复,提升小目标检测能力。(小目标): 从 0.51 AP → 0.63 AP (+24%):采用ESPCN的高效亚像素卷积,避免传统插值的信息损失。:从通道级(SE)到空间级(Spatial)的多粒度控制。:结合浅层细节和深层语义,恢复小目标的纹理信息。

u012133341的博客 840

KMP算法(字符串匹配算法)详解及java实现

KMP算法是BF(Brute Force)算法的一种改进算法,什么是BF算法这里不多做解释。 1.KMP算法实现思路:   每当一趟匹配过程中出现字符比较不等时,不需要回溯主串上面的指针i,而是利用已经计算出的模式串P在j位置前面的子串P0...Pj-1的部分匹配值k将模式向右滑j-k个字符,然后继续进行比较。   2.理解"前缀"、"后缀"和“部分匹配值”的概念:

syy0377的专栏 1万+

LLC 谐振转换器中为什么需要 ( L_m )(励磁电感)

在每个模态中,励磁电感 ( L_m )、谐振电感 ( L_r ) 和谐振电容 ( C_r ) 分别承担着储存和释放能量、维持谐振电流和电压波形的任务。Q1和Q2的交替导通确保了这些元件能够在不同的模态下实现能量的有效传输和谐振状态的维持。励磁电感 ( L_m ) 在这一过程中起着不可或缺的作用,确保了电路的高效运行和稳定性。

weixin_43199439的博客 3653

[deprecated]第九章:SVM机制: 9-2 Linux HMM原理与实现详解

Linux内核HMM(异构内存管理)子系统为异构计算平台提供统一内存管理机制,支持CPU与GPU等设备共享虚拟地址空间,实现零拷贝数据访问。其核心功能包括:1)统一虚拟地址空间,设备可直接访问CPU进程内存;2)实时页表同步与失效通知,确保地址空间一致性;3)支持设备端page fault处理;4)管理多种内存类型(系统内存、设备私有内存等)。HMM通过mmu_interval_notifier机制感知地址空间变化,提供标准API简化驱动开发,显著提升异构计算性能和数据传输效率。

图形/计算GPU的驱动与虚拟化技术分享园地 2539

【字符串匹配算法:BF & KMP】

从BF到KMP

Q1697354625 543

2025年5月架构设计师论文真题回顾,附写作技巧、所涉知识点及参考范文(三)

本文主要回顾2025年上半年(2025-5-24)系统架构设计师考试下午论文的题目,同时附带写作技巧、所涉知识点及参考范文。试题三:多模型数据库及应用。

一几文的编程学习笔记。 629

串的模式匹配之KMP算法

想理一理KMP算法的学习思路,但是不会制作动图表达,暂时就用文字描述,尽量表达清晰吧。 注:看多了各种解说会发现,有些算法讲解和代码实现有出入,主要是因为针对的字符串存储方式不一样,要先明确串的值从0还是1单元开始存放。 模式匹配 给定主串s和子串t,则在s中找到t的过程称为模式匹配,其中t称为模式。如果在s中找到等于t的子串,则匹配成功,返回t在s中首次出现的存储位置,否则匹配失败,返回-1。 ...

foolish_boy2的博客 886

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Statistics and Machine Learning Toolbox

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

算法基础(一):串匹配问题(BF,KMP算法)

在KMP算法中计算子串B的部分匹配表时,我们只需要关注B本身,而不需要考虑B要在哪个字符串中进行匹配。这么做是对的,可是这没有确切依据,凭借的是"直觉"

Fattiger1234的博客 1338

温度PID控制PLC程序

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

【数据结构】KMP算法

设定主串的长度为n,字串的的长度为m。传统的暴力字符串匹配算法理论上最多需要花费O(nm)的时间复杂度才能完成串的匹配操作,但是在实际使用中,往往也能够以接近O(m+n)的时间复杂的完成匹配操作,因此现在仍被广泛使用。而KMP算法则理论上最坏可以在O(m+n)的时间复杂度内完成字符串的匹配操作。暴力匹配算法低效的根源是因为会进行很多次重复的匹配操作,即主串中存在回溯。而KMP算法中,主串的指针的移动方向一直是往右的。...

冷芝士鸭的学习笔记 1818

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

字符串匹配之KMP算法

KMP算法的难点在于next数组和前缀表 KMP算法流程: 假设现在文本串 S 匹配到 i 位置,模式串 P 匹配到 j 位置 如果 j = -1,或者当前字符匹配成功(即 S[i] == P[j] ),都令 i++,j++,继续匹配下一个字符; 如果 j != -1,且当前字符匹配失败(即 S[i] != P[j] ),则令 i 不变,j = next[j]。此举意味着失配时,模式串 P相对于...

MyNotes 255

KMP算法讲解与实现

KMP算法的讲解与实现

明朗晨光的专栏 1971

最通俗易懂的KMP算法详解,遇到字符串匹配算法不再怕了

有些算法,适合从它产生的动机,如何设计与解决问题这样正向地去介绍。但KMP算法真的不适合这样去学。最好的办法是先搞清楚它所用的数据结构是什么,再搞清楚怎么用,最后为什么的问题就会有恍然大悟的感觉。我试着从这个思路再介绍一下。大家只需要记住一点,PMT是什么东西。然后自己临时推这个算法也是能推出来的,完全不需要死记硬背。KMP算法的核心,是一个被称为部分匹配表(Partial Match Table...

u013095264的博客 364
上一篇: 【IEEE754制32位浮点数】与十进制相互转换
下一篇: 二叉树的前序、中序、后序递归算法
快苏排序OAO
博客等级 码龄5年 273粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

快苏排序OAO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值