KMP串中的模式匹配算法及从next[]到nextVal[]

KMP串中的模式匹配算法

一般的匹配算法:


KMP基本概念引入:

但是,其实我们会发现,上面的中间两个匹配步骤是没有必要的,因为他们的第一个匹配字母就不相同,完全没有可比性,而当我们在第四次匹配的时候,其
实我们从模式串中就可得知,只有当模式串滑到这个地方的时候,它的匹配才是最有价值的,因为从模式串中我们可以得知,最后一个C的前一个字母是a,而在模
式串中的第二个字母b的前一个字母也是a,再无其他,从第一步匹配的结果我们可以得知,模式串中的最后一个字母c与主串中的b匹配失败(读者们是否注意
到,我们前面提到的,这个c的前一个字母是a哦),
而从模式串中我们可以得知,即我们完全可以跳过上面匹配步骤的中间的两步,那是否读者在担心中间会错过原本可以匹配的呢,完全不必担心,因为在我们的模式
串中就记录了,前面就连一个能和a进行匹配的字母都没有。

那么,当某一轮匹配失败时,模式项的滑动位置如何确定,即模式项中的那一项来和主串的的b(黄色格子内)对齐,从而省略中间的比较项,我们可以将这一项的index设置为K,如上的模式项,K为2
注意在串中,数组的第一项是用来记录数据个数的。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

如上所述,KMP算法的关键,即根据模式串找到那个K(下面列出K所需要满足的条件)(当主串中第i个字符与子串中第j个字符失配时):

设主串为:s1s2……sn 子串为:p1p2……pn

则K的取值应满足:



----------------------》》》》》》》》》》》》》》》


归根结底,找模式串与串头重复的子串:

实例:


那么:如何找到模式串中的每一个元素的K,也即如图中的next数组:

代码敬上:

void get_next(SString T,int next[])
 { /* 求模式串T的next函数值并存入数组next 算法 4.7 */
   int i=1,j=0;
   next[1]=0;
   while(i<T[0])
     if(j==0||T[i]==T[j])
     {
       ++i;
       ++j;
       next[i]=j;
     }
     else
       j=next[j];  /*精髓之处  当前面已经有了相似的比较的时候,直接借用前面的结果    两个大体的环境相似,则这两个大体的环境间就会存在相同的匹配环境,即已经记录的环境,如果错过了一些已经匹配了子串,则会导致K值比实际的要小,即后面的匹配必须依赖前面的匹配结果*/
 }

上面代码解释:

1:j=0时,i和j都要相加并给next赋值

2:T[i] = T[j] ,i和j都要相加并给next赋值

如果上面两个都不满足,则需要将 j 往前指向,那么问题就来了,为什么不直接 j = 1,而需要将 next[j]的值赋给 j
呢,其实就如我在代码中所讲,不妨也举个栗子说明一下。

其实可以总结为一下几点,K的目的是定位偏移量的index,失配项的前面有几个与模式项的头部相等的,K就为这些数加1,而其实这几个数,正是我们所要跳过的。

KMP算法的劣势,其实,从寻找K的过程中我们就可以看出,KMP算法重度依赖模式串与主串存在许多部分匹配


KMP算法从next[]到nextVal[]

上面,我们谈到了一个模式串K值的记录数组next[],详细可看那篇文章,其实,前面定义的next[]数组是有一定缺陷的,下面我面我将针对一种情况进行举例:


如上图,如果按照之前的方法所获取的next[]数组的话,当两个字符串匹配到上图的情况是,将会出现如下图的情况:


我们发现,从step1到step3所走的路都是浪费的,因为都是用同一个字母(a)和b去比,而这个计算机也是哼容易识别的,所以对于next[]的改进是行的通的。

究其原因,为什么我会说上面的3个步骤是白走的呢,以为这是三个连续的相等的a,因此我们可以从第一步直接跳到第四步,即:得到的数组next[j] =
k,而模式串p[j] = p[k],当主串中的s[i] 和 p[j]
匹配失败时,不需要再和p[k]比较,而直接和p[next[k]]进行比较,当然可以一直迭代往前。

即:


代码如下:

void get_nextVal(SString T, int nextVal[])
 {
     int i = 1, j = 0;
     nextVal[1] = 0;

     while( i <= T[0])
     {
         if(j == 0 || T[i] == T[j])
         {
             j++;
             i++;
             if(nextVal[i] == nextVal[j])
             {
                 nextVal[i] = nextVal[j];
             }
             else
             {
                 nextVal[i] == j;
             }

         }
         else
         {
             j = nextVal[j];
         }
     }

 }

注意,所求的永远是前一个的K(写给自己的)嘻嘻

时间: 2024-08-01 06:55:22

KMP串中的模式匹配算法及从next[]到nextVal[]的相关文章

图解字符串的朴素模式匹配算法

复习串的朴素模式匹配算法 模式匹配 : 子串定位运算,在主串中找出子串出现的位置. 在串匹配中,将主串 S 称为目标(串),子串 T 称为模式(串).如果在主串 S 中能够找到子串 T, 则称匹配成功,返回 第一个 和 子串 T 中 第一个字符 相等 的 字符 在主串 S 中的 序号,否则,称匹配失败,返回 0.  算法思想: 从主串 S 的第 pos 个字符起和模式 T 的第一个字符比较之,若相同,则两者顺次的去比较后续的每一个字符,否则从主串 S 的下一个字符起再重新和模式 T 的字符比较之

KMP模式匹配算法概述

我们经常会遇到一种情况是匹配两个字符串,看strPar中是否含有str子串,如果有则返回子串在父串strPar中的位置,如果不存在则返回false. 很明显,我们可以通过暴力求解的方式解决该问题.即从strPar第一个字符和子串进行比较,若成功则返回第一个0,若不成功,再第二个字符开始比较,这样的时间复杂度为O(M*N).可以看出,这个复杂度是相当高的,那么我们有没有一种复杂度会降低呢?显然,有一种叫做KMP算法可以大大降低复杂度O(M+N).该算法通过记忆的方式,避免了很多无用功. 比如字符.

KMP算法中的前缀函数问题

问题描述 KMP算法中的前缀函数问题 复习算法与数据结构这课的KMP算法,到现在对前缀函数很困惑.各位大牛们就举个例子来说说吧. 字符串"abcaababc" 求其KMP前缀函数. 我求出来next[i]:{-1,0,0,-1,1,0,2,0,0},这是不是KMP前缀函数啊? 解决方案 假设给定的模式串是:abcdabd, 从左到右遍历整个模式串,那么各个子串的前缀后缀为: 子串 前缀 后缀 最大公共长度 a null null 0 ab a b 0 abc a, ab c, bc 0

超高速软件多模式匹配算法

问题描述 超高速软件多模式匹配算法:本算法以经典多模式匹配算法WU-Manber算法为基础,对其进行了结构化改进,达到了超高速的水平.以下是与当前(确切地说,应该是本算法之前)代表中国最高水平的中科院I3S特征串扫描算法的对比测试结果(同在2.0GHZCPU上测试):4字节长的模式:2000条模式5000条模式1万条模式3万条模式5万条模式10万条模式i3s2.5Gbps1.2Gbps560Mbps400Mbps160Mbps100Mbps本算法2.5Gbps2.0Gbps1.7Gbps1.2G

DotNet Framework源代码中的模式(一)——目录

DotNet Framework源代码中的模式(二)--前言 DotNet Framework源代码中的模式(三)--Iteartor(迭代器模式) DotNet Framework源代码中的模式(四)--Abstract Factory(抽象工厂模式) DotNet Framework源代码中的模式(五)--Decorator(装饰模式) DotNet Framework源代码中的模式(六)--Prototype(原型模式) DotNet Framework源代码中的模式(七)--Factor

Word2013中兼容模式如何转换

  Word2013中兼容模式如何转换 ①打开文档,我们看到文档是兼容模式. ②现在我们要进行转换,单击文件--信息--转换--兼容模式. ③出现一个Microsoft Word提示框,我们单击确定按钮. ④现在转换完成,可以看到现在的文档已经不是兼容模式了.

PhotoShop中Lab模式调色理论详细介绍

本例向朋友们介绍在PS的LAB模式下调色的原理以及通过实例来详细讲解LAB模式计算调色的运用, 希望能给对PS调色感兴趣的朋友带来帮助~~ 现在来说说计算这个话题,这是个大题目,要一下子说清楚这个,要花不少的时间,所以用闲谈这个方 式可以随便就这个聊聊. 在说清楚这个之前,先了解下什么是Lab模.这个模式是不依赖于光线和颜料,在理论上包括人眼可以看 见的所有色彩模式.简单地说,就是模仿人眼视角习惯而产生的模式. "Lab 中的数值描述正常视力的人能够看到的所有颜色.因为 Lab 描述颜色的显示方

asp.net Silverlight中的模式窗体_实用技巧

其实在Silverlight中开发模式窗体并不难,比在Html里面用div来构造容易多了,但是要做到具有重用性和规范性还是要下一点工夫的.如果SL的开发朋友们想偷一点懒,直接用些现成写好的模式窗体代码的话,我在这里介绍一个SL的框架,叫SilverlightFX,里面就有一个Form类,只要你的xaml类继承了Form类就可以很方便地使用模式窗体了.具体方面可以参照他的sample工程,这里给出SilverlightFX的连接给大家 http://projects.nikhilk.net/Sil

php 时间函数格式-PHP时间函数中表示格式的串中P或PT是什么意思?

问题描述 PHP时间函数中表示格式的串中P或PT是什么意思? 如题,在$interval = new DateInterval('P2W')中2W表示两周,但前面的P是什么用法,还看到有写PT的.请提供参考链接,谢谢. 解决方案 http://php.net/manual/en/class.dateinterval.php