串的匹配 (KPM算法由来引导)

article/2025/10/9 8:33:04

前言:

引入 KPM 算法的前提是 , B-F算法中,匹配失败后不必完全从头再来 , 找到可以利用的信息 , 可以进行跳跃性匹配

下面 , 我们对字符串匹配的一些思路进行剖析:

开始匹配的操作 ,我们会让 目标串 s , 和 模式串进行对齐,就像如图所示:

e55678958f6e4c9a99c0f57ca549f469.png


 我们当然是从串 t 的头结点开始对比 

0194aac473d04c78965142bbe0f92031.png

   对比 第一个元素 , 符合


dfb2d1a5096a41d7a7ca14163a29b810.png

然后对比第二个 元素符合


3f744375a9464670baa336dd1f49c60c.png

 对比第三个元素 , 不相等


此时 , 按照我们 B-F算法 , 不相等 , 我们就需要重新从 串 s 的第二个元素, 进行和 串 t 进行比较了  

如图 : 

ce7e713e54524aa7a8979c68c4bac560.png

但是 , 此时我们注意到 , 我们开头已经对比了 串 t 和 串 s 两个元素重合 , 并且他们互不相等 , 说明再次把串 t 的开头 和  串 s 的第二个元素是不明智的选择

因为 , 我们既然要寻找和串 t 相等的串 , 首先要保证的就是 , 串 t 的头结点要和串 s 元素先匹配上, 然后我们才能继续后续的对比 

我们现在前两个节点已经重合, 并且他们互不相同 , 就没必要再移动一位了重合比较了

所以 , 我们直接 将串 t 开头和 串 s 的第三个元素进行比较即可

e74fd960d1a4443689b5b29d0399741d.png


我们接着对比 , a 相等 , b 相等 , c 相等 , a 相等 , 当比较到串 t 的第五个元素时 , b 和 c 不相等 ,

此时, 我们如果还采取 B-F算法当然也是可以的 , 逐个将 串t 和 对比初始位置后移的串 s 进行对比 ,

edeea621f2f24a4c875eca92cd12b3a1.jpeg

 ccefb8f913a14ee09ea24581236e4aa5.png

922a63afa5524188a61194a387303453.png


我想 , 上面的步骤有些是没必要的 , 因为我们此时分析 :

9469781c1c0a4bf09b61116d3ad223e3.png

串 t 此时我们已经对比了五个元素 , 前 四个已经对比符合了 ,

我们现在第五个元素, 对比到了不同元素 , 我们能直接把对比过的字符串抛弃吗? 

意思就是说 , 我们能下定论, 已经对比过的字符, 不会再有可以匹配的子串了呢?

能直接如下图所示吗? 

聪明的我们, 会发现 , 我们就算对比重合过的字符 , 遇到不同的字符 , 我们也不能直接把 比较重合过的字符全部抛弃 , 除非对比过的字符互不相同 , 那 我们直接略过也没事 , 

但是如果, 我们对比过的字符 , 有和 串 t 头结点相等的节点 , 我们就不能略过了 

上图, 标蓝 部分 , 我们在我们在对比的时候已经对比过了 , 我们会发现  串 t 里面有两个头节点 , 那当我对比到 第二个头结点之后的一个节点的时候 , 我们如果发现不同字符 , 我们就可以把第二个头结点当作头结点, 然后后续接着让 串 t 的第二个节点和 串 s 进行比较


我们上面的意思就是 , 假如现在有一个

e16e24aa04494820bf5469c9349f89aa.png

当串 s 和 串 t 元素进行比较时 , 当一个字符不匹配的时候 , 我们必然要让 串 t 开头 往后移动

但是逐个比较的话 , 有些节点是没必要比较的 , 如下图:

明明知道, 前五个字符两个串对比符合了, 并且五个字符互不相同 , 就没必要逐个错峰比较了,

直接跳过这五个元素 , 让 串 t 第一个元素和串 s 第五个元素进行比较

但是 , 有的情况 , 当比较到不同字符时 , 那个字符前面有和头结点相同的子串的话 ,我们就可以直接把 头结点子串的位置, 拉到 不同字符前面的头节点子串的位置 , 这样就不会错过重合的机会了.

如下图

bd08cbe32a724895b6e694ec0e6c8b24.png

经过上面的分析 , 我们得出, 如果要准确把握模式串 t 每个字符 比较到不同的字符的时候 ,应该跳到串 t 哪个字符再和 串 s那个元素进行比较 , 就需要找出每个字符前面的和头结点子串相等的子串 , 

那当子串有很多呢 ? 找哪一个呢?

我们就需要引入前缀串和后缀串 

作者能力有限 , 下一篇博客 ,转载大佬解析 ,我这里只做思路引导 . 

c代码:

#include <stdio.h>
#include "sqString.h"
void GetNext(SqString t , int next[])
{int j,k;j = 0;k = -1;next[0] = -1;while(j<t.length-1){if(k == -1 || t.data[j] ==t.data[k]){j++;k++;next[j] = k;}else{k = next[k] ;}}
}
//进行验证
int KMPIndex(SqString s, SqString t)
{int next[MaxSize],i=0,j=0;GetNext(t,next);while(i<s.length && j<t.length){if(j == -1 || s.data[i] == t.data[j]){i++;j++;}else{j = next[j];}}if(j >= t.length){return(i - t.length);}else{return(-1);}
}
int main()
{SqString s,t;StrAssign(s,"ababcabcacbab");StrAssign(t,"abcac");printf("s:");DispStr(s);printf("t:");DispStr(t);printf("位置: %d\n",KPMIndex(s.t));return 0;
}


http://chatgpt.dhexx.cn/article/XoMiuCRK.shtml

相关文章

KPM匹配算法

KPM匹配算法 不管在工作中还是学习中经常会遇到串的模式匹配&#xff0c;一般来说&#xff0c;串的模式匹配算法主要是两种【朴素模式匹配和KPM模式匹配】一种改良【KPM的改良】&#xff0c;下面先看一下朴素模式匹配&#xff1a;朴素模式匹配主要思想比较简单也比较粗暴&…

KPM算法

算法 字符串匹配之朴素算法和KMP算法及JAVA代码实现 2017年06月02日 10:31:12 阅读数&#xff1a;941 暴力匹配算法 假设现在我们面临这样一个问题&#xff1a;有一个文本串S&#xff0c;和一个模式串P&#xff0c;现在要查找P在S中的位置&#xff0c;怎么查找呢&#xff1…

Python KPM算法

知识点说明&#xff1a; 先说前缀&#xff0c;和后缀吧 比如有一个串&#xff1a;abab 则在下标为3处的&#xff08;前缀和后缀都要比下标出的长度小1&#xff0c;此处下标为3出的长度是4&#xff09; 前缀为&#xff1a;a,ab,aba 后缀为&#xff1a;b,ba,bab 一、要获取…

KPM算法——数据结构|复习局|串|复杂模式匹配算法|二维数组解决KPM

数据结构复习局——KPM算法 何为KPM&#xff1f;事先规则状态匹配dp——状态转移图状态X获得dp数组值看看图再理解下 写在前面&#xff1a; 本文仅为作者个人学习记录&#xff0c;详细具体内容参考自知乎大佬labuladong &#x1f448;点击与大佬&#x1f93a;击剑&#x1f93a;…

KMP算法原理及实例

KMP是为了解决串的匹配问题。 一、基础知识 1、概念 1.串的匹配问题&#xff1a;就是在一个长的主串s中找到另一个的短的子串t。 2.目标串&#xff08;主串\文本串&#xff09;&#xff1a;被匹配的母串&#xff0c;串s被称为目标串。 3.模式串(子串&#xff09;&#xff1a…

KPM算法思想及实现

一、比较暴力算法和KMP算法 1、暴力算法&#xff1a; 双指针遍历主串和子串&#xff0c;当发现主串和子串不匹配时&#xff0c;双指针同时回溯 2、KMP算法&#xff1a; 双指针遍历主串和子串&#xff0c;当发现主串和子串不匹配时&#xff0c;通过比较子串的next数组只回溯…

正定矩阵的性质

正定矩阵的定义&#xff1a;若矩阵A是n阶方阵&#xff0c;并且它的二次型大于0&#xff0c;即&#xff0c;则矩阵A是正定矩阵。 正定矩阵的性质&#xff1a; 正定矩阵的所有特征值都为正数。正定矩阵行列式为正数两个正定矩阵的和为正定矩阵&#xff08;两个正定矩阵的乘积不…

顺序主子式

设A为 阶矩阵&#xff0c;子式 称为A的i阶顺序主子式。 [1] 对于 阶的矩阵A&#xff0c;其共有n阶顺序主子式&#xff0c;即矩阵A的顺序主子式由 共n个行列式按顺序排列而成。

【矩阵论笔记】平方根分解

定义 例子 首先判断顺序主子式。 R矩阵每一行除以对角元 平方根分解推导 因为A的分解是唯一的&#xff0c;可以得到 L R T LR^{T} LRT 例题 待定系数法

MATLAB_数值计算_用平方根法解线性方程组—(Cholesky分解)

利用对称正定矩阵的乔累斯基分解求解对称正定方程组的方法称为平方根法对称正定矩阵A的对角元为正实对称矩阵A正定的充要条件是A的所有特征值为正对称正定矩阵非奇异&#xff0c;其逆亦为对称正定矩阵实对称矩阵A正定的充要条件是A的所有顺序主子式为正正定矩阵的顺序主子阵是正…

正定与半正定矩阵,判别的方法不能混用,否则出错

坑&#xff1a;特征值有0可以知道该矩阵不可能正定&#xff0c;那可以用顺序主子式判断是否为半正定吗&#xff1f; 答案&#xff1a;不能 例子&#xff1a;A,特征值为一个0&#xff0c;两个正数>那就是半正定啦呀 但是&#xff0c;主子式二阶小于0那就不正定了呀两种方法…

线性代数【11】二次型

前言&#xff1a; 矩阵表达的是线性关系的方程组&#xff0c;但是&#xff0c;客官世界&#xff0c;是包括稍微复杂的&#xff0c;二次方程。 尤其几何中&#xff0c;有二次曲线&#xff0c;二次型&#xff0c;就是一个多元函数&#xff0c;是多个变量的二次&#xff0c;齐次…

Lyapunov稳定性分析1(正定函数、二次型正定判定)

一、 正定函数 1.1 定义&#xff1a; 令V(x)是向量x的标量函数&#xff0c;S是x空间包含原点的封闭有限区域。如果对于S中的所有x&#xff0c;都有&#xff1a; 则V(x)是正定的&#xff08;半正定&#xff09;。正定函数更直观的描述如下图所示&#xff1a; 如果条件(3&a…

牛顿法为什么要保证Hessian矩阵正定

牛顿法为什么要保证Hessian矩阵正定&#xff1a; 实际中&#xff0c;需要求出Hessian的逆矩阵&#xff0c;只有正定矩阵&#xff0c;才可以求出逆矩阵。 正定矩阵&#xff1a;特征值全大于0&#xff1b;各阶主子式全大于0.

正定矩阵的相关知识

一、正定矩阵的定义&#xff1a;若矩阵A是n阶方阵&#xff0c;并且它的二次型大于0&#xff0c;即 则矩阵A是正定矩阵。 二、正定矩阵的性质&#xff1a; 1.正定矩阵的所有特征值都为正数。 2.正定矩阵行列式为正数 3.两个正定矩阵的和为正定矩阵&#xff08;两个正定矩阵的乘…

顺序主子式的英文翻译(定义)

顺序主子式的英文翻译&#xff08;定义&#xff09; 为了查明顺序主子式的英文翻译&#xff0c;我在国内知网翻译助手、金山词霸等诸多翻译系统查了一下&#xff0c;给出的答案不外乎以下几个答案。 &#xff08;知网翻译助手的答案&#xff09; 我喜欢刨根问底&#xff0c;很明…

030 正定二次型及判别法之定义法、特征值法、顺序主子式法

030 正定二次型及判别法之定义法、特征值法、顺序主子式法

matlab-线性代数 det 各阶主子式、余子式、代数余子式

2019独角兽企业重金招聘Python工程师标准>>> matlab : R2018a 64bit     OS : Windows 10 x64typesetting : Markdown    blog : my.oschina.net/zhichengjiu    gitee : gitee.com/zhichengjiu 各阶主子式 code clear clca=[1 2 3;4 5 6;6 7 8…

主子式、顺序主子式、余子式、代数余子式

K阶子式 [ 1 ] ^{[1]} [1] (Minor) 以3阶行列式为例&#xff1a; ∣ a 1 a 2 a 3 b 1 b 2 b 3 c 1 c 2 c 3 ∣ \left| \begin{array} {ccc} a_1 & a_2 & a_3 \\ b_1 & b_2 & b_3\\ c_1 & c_2 & c_3 \end{array} \right| ∣∣∣∣∣∣​a1​b1​c1​​…

简单推导:关于矩阵主子式的几点性质

1.名词介绍: 特征多项式&#xff1a;在数域P上的某个方阵A,则行列式即为其特征多项式&#xff0c;简记为; 逆序数&#xff1a;1,2,...n的某个排序相对自然序列相反的个数&#xff1b;记为&#xff1a; 主子式&#xff1a;某个行列式的部分列和部分行&#xff1a;行号和列号一…