基于MATLAB的数据结构与算法_KMP

合集下载

模式匹配KMP算法实验报告

模式匹配KMP算法实验报告

实验四:KMP算法实验报告一、问题描述模式匹配两个串。

二、设计思想这种由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现的改进的模式匹配算法简称为KM P算法。

注意到这是一个改进的算法,所以有必要把原来的模式匹配算法拿出来,其实理解的关键就在这里,一般的匹配算法:int Index(String S,String T,int pos)//参考《数据结构》中的程序{i=pos;j=1;//这里的串的第1个元素下标是1while(i<=S.Length && j<=T.Length){if(S[i]==T[j]){++i;++j;}else{i=i-j+2;j=1;}//**************(1)}if(j>T.Length) return i-T.Length;//匹配成功else return 0;}匹配的过程非常清晰,关键是当‘失配’的时候程序是如何处理的?为什么要回溯,看下面的例子:S:aaaaabababcaaa T:ababcaaaaabababcaaaababc.(.表示前一个已经失配)回溯的结果就是aaaaabababcaaaa.(babc)如果不回溯就是aaaaabababcaaaaba.bc这样就漏了一个可能匹配成功的情况aaaaabababcaaaababc这是由T串本身的性质决定的,是因为T串本身有前后'部分匹配'的性质。

如果T为a bcdef这样的,大没有回溯的必要。

改进的地方也就是这里,我们从T串本身出发,事先就找准了T自身前后部分匹配的位置,那就可以改进算法。

如果不用回溯,那T串下一个位置从哪里开始呢?还是上面那个例子,T为ababc,如果c失配,那就可以往前移到aba最后一个a的位置,像这样:...ababd...ababc->ababc这样i不用回溯,j跳到前2个位置,继续匹配的过程,这就是KMP算法所在。

KMP算法的详细解释

KMP算法的详细解释

KMP算法的详细解释什么是kmp算法呢?这是⼀个处理字符串的算法,⽤来判断给出的模式串p是否存在于⽂本串t中(p的长度⼩于t)。

在本⽂中,字符串储存在字符数组中,并且第⼀个字符放在下标为1的元素中。

那么如何理解kmp算法呢?⾸先要从最朴素的匹配算法说起。

我们判断p是否存在于t中,最原始的⽅法就是从头到尾⼀直遍历。

定义变量i为⽂本串t中的下标,定义变量j为模式串p中的下标,然后i表⽰看⽂本串的前i个字符,j表⽰判断这前i个字符组成的⼦串中,长度为j的前后缀是否相等。

如果t[i] = p[j],则i与j同时后移⼀位,⽐较下⼀位是否相同,如果t[i] != p[j],则表⽰串t在i位置处“失配”,需要重新进⾏匹配,i保持不动,并且j 必须返回到模式串p的开头,也就是相当于回退到1,然后再次进⾏循环。

如果t的长度为m,p的长度为n时,这样做的时间复杂度为O(m*n)kmp就是在这种最原始匹配算法的基础之上的改进算法。

Kmp的改进之处在哪⾥呢?上⾯这种复杂度最⼤的朴素⽅法中,有⼀个步骤,当“失配”时,我们的i不移动,但是j需要回到串p的开头,这样每⼀次失配,我们都需要再从模式串的开头重新开始匹配,相当于将j直接回退到1,然后再从1开始去试满⾜的最⼤的相同前后缀长度,多了好多次循环,聪明的科学家们想到的办法是:假设现在有这样⼀种情况:在遍历到⽂本串t的的前i-1个字符组成的⼦串之后,我们已经确定了该⼦串中的长度为j-1的前后缀是相同的,那么现在在考虑下⼀个字符(第a个)时发⽣失配,也就是第a个字符不等于第b个,我们不想让b直接回退到1,⽽是回退到1和b之间的某个值,以减⼩复杂度。

我们先放下这个问题,思考另外⼀个问题:如果要求⼀个字符串中相同的前缀和后缀的最长长度,怎么求呢?和上⾯的kmp其实特别像,还是分治的思想:假设我们现在已经看到了字符串的前i-1个元素,并且在这i-1个元素的⼦串中,长度为j-1的后缀和前缀是⼀样的,表⽰匹配到了j-1的长度,那么我们就可以考虑第字符串中第i个元素是否和第j个元素相同了,如果相同就继续匹配下去,如果不同,j仍要回退,但是不能把j直接回退到1然后递增地去判断,这样复杂度太⼤。

数据结构算法之KMP算法

数据结构算法之KMP算法
printf("Locate the substring with the simple method.\n\n");
position = simpleLocate( str, pat );
if ( position == 0 )
{
printf("\nThe \"pat\" can not be found in \"str\".\n", position);
printf("%s\n", pat);
printf("\nThe length of \"str\" is %d.\n", STRLENGTH);
printf("\nThe length of \"pat\" is %d.\n", PATLENGTH);
printf("\n\n************************************************************************\n\n");
int j = 1;
int nextval[100] = {0};
extern long comparetimes;
comparetimes = 0;
getnextval(nextval, pattern);
while ( ( orign[i] != '\0' ) && ( pattern[j] != '\0' ) )
return ( i - j + 1 );
else
return 0;

KMP算法以及优化(代码分析以及求解next数组和nextval数组)

KMP算法以及优化(代码分析以及求解next数组和nextval数组)

KMP算法以及优化(代码分析以及求解next数组和nextval数组)KMP算法以及优化(代码分析以及求解next数组和nextval数组)来了,数据结构及算法的内容来了,这才是我们的专攻,前⾯写的都是开胃⼩菜,本篇⽂章,侧重考研408⽅向,所以保证了你只要看懂了,题⼀定会做,难道这样思想还会不会么?如果只想看next数组以及nextval数组的求解可以直接跳到相应部分,思想总结的很⼲~~⽹上的next数组版本解惑先总结⼀下,⼀般KMP算法的next数组结果有两个版本,我们需要知道为什么会存在这种问题,其实就是前缀和后缀没有匹配的时候next数组为0还是为1,两个版本当然都是对的了,如果next数组为0是的版本,那么对于前缀和后缀的最⼤匹配长度只需要值+1就跟next数组是1的版本⼀样了,其实是因为他们的源代码不⼀样,或者对于模式串的第⼀个下标理解为0或者1,总之这个问题不⽤纠结,懂原理就⾏~~那么此处,我们假定前缀和后缀的最⼤匹配长度为0时,next数组值为1的版本,考研⼀般都是⽤这个版本(如果为0版本,所有的内容-1即可,如你算出next[5]=6,那么-1版本的next[5]就为5,反之亦然)~~其实上⾯的话总结就是⼀句话next[1]=0,j(模式串)数组的第⼀位下标为1,同时,前缀和后缀的最⼤匹配长度+1即为next数组的值,j所代表的的是序号的意思408反⼈类,⼀般数组第⼀位下标为1,关于书本上前⾯链表的学习⼤家就应该有⽬共睹了,书本上好多数组的第⼀位下标为了⽅便我们理解下标为1,想法这样我们更不好理解了,很反⼈类,所以这⾥给出next[1]=0,前缀和后缀的最⼤匹配长度+1的版本讲解前⾔以及问题引出我们先要知道,KMP算法是⽤于字符串匹配的~~例如:⼀个主串"abababcdef"我们想要知道在其中是否包括⼀个模式串"ababc"初代的解决⽅法是,朴素模式匹配算法,也就是我们主串和模式串对⽐,不同主串就往前移⼀位,从下⼀位开始再和模式串对⽐,每次只移动⼀位,这样会很慢,所以就有三位⼤神⼀起搞了个算法,也就是我们现在所称的KMP算法~~代码以及理解源码这⾥给出~~int Index_KMP(SString S,SString T,intt next[]){int i = 1,j = 1;//数组第⼀位下标为1while (i &lt;= S.length &amp;&amp; j &lt;= T.length){if (j == 0 || S.ch[i] == T.ch[j]){//数组第⼀位下标为1,0的意思为数组第⼀位的前⾯,此时++1,则指向数组的第⼀位元素++i;++j; //继续⽐较后继字符}elsej = next[j]; //模式串向右移动到第⼏个下标,序号(第⼀位从1开始)}if (j &gt; T.length)return i - T.length; //匹配成功elsereturn 0;}接下来就可以跟我来理解这个代码~~还不会做动图,这⾥就⼿画了~~以上是⼀般情况,那么如何理解j=next[1]=0的时候呢?是的,这就是代码的思路,那么这时我们就知道,核⼼就是要求next数组各个的值,对吧,⼀般也就是考我们next数组的值为多少~~next数组的求解这⾥先需要给出概念,串的前缀以及串的后缀~~串的前缀:包含第⼀个字符,且不包含最后⼀个字符的⼦串串的后缀:包含最后⼀个字符,且不包含第⼀个字符的⼦串当第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j]=S的最长相等前后缀长度+1与此同时,next[1]=0如,模式串"ababaa"序号J123456模式串a b a b a anext[j]0当第六个字符串匹配失败,那么我们需要在前5个字符组成的串S"ababa"中找最长相等的前后缀长度为多少再+1~~如串S的前缀可以为:"a","ab","aba","abab",前缀只不包括最后⼀位都可串S的后缀可以为:"a","ba","aba","baba",后缀只不包括第⼀位都可所以这⾥最⼤匹配串就是"aba"长度为3,那么我们+1,取4序号J123456模式串a b a b a anext[j]04再⽐如,当第⼆个字符串匹配失败,由前1个字符组成的串S"a"中,我们知道前缀应当没有,后缀应当没有,所以最⼤匹配串应该为0,那么+1就是取1~~其实这⾥我们就能知道⼀个规律了,next[1]⼀定为0(源码所造成),next[2]⼀定为1(必定没有最⼤匹配串造成)~~序号J123456模式串a b a b a anext[j]014再再⽐如,第三个字符串匹配失败,由前两个字符组成的串S"ab"中找最长相等的前后缀长度,之后再+1~~前缀:"a"后缀:"b"所以所以这⾥最⼤匹配串也是没有的长度为0,那么我们+1,取1序号J123456模式串a b a b a anext[j]0114接下来你可以⾃⼰练练4和5的情况~~next[j]011234是不是很简单呢?⾄此,next数组的求法以及kmp代码的理解就ok了~~那么接下来,在了解以上之后,我们想⼀想KMP算法存在的问题~~KMP算法存在的问题如下主串:"abcababaa"模式串:"ababaa"例如这个问题我们很容易能求出next数组序号J123456模式串a b a b a anext[j]011234此时我们是第三个字符串匹配失败,所以我们的next[3]=1,也就是下次就是第⼀个字符"a"和主串中第三个字符"c"对⽐,可是我们刚开始的时候就已经知道模式串的第三个字符"a"和"c"不匹配,那么这⾥不就多了⼀步⽆意义的匹配了么?所以我们就会有kmp算法的⼀个优化了~~KMP算法的优化我们知道,模式串第三个字符"a"不和主串第三个字符"c"不匹配,next数组需要我们的next[3]=1,也就是下次就是第⼀个字符"a"和主串中第三个字符"c"对⽐,之后就是模式串第⼀个字符"a"不和"c"匹配,就是需要变为next[1]=0,那么我们要省去步骤,不就可以直接让next[3]=0么?序号J12345模式串a b a b anext[j]01123nextval[j]00那么怎么省去多余的步骤呢?这就是nextval数组的求法~~nextval的求法以及代码理解先贴出代码for (int j = 2;j &lt;= T.length;j++){if (T.ch[next[j]] == T.ch[j])nextval[j] = nextval[next[j]];elsenextval[j] = next[j];}如序号J123456模式串a b a b a anext[j]011234nextval[j]0⾸先,第⼀次for循环,j=2,当前序号b的next[2]为1,即第⼀个序号所指向的字符a,a!=当前序号b,所以nextval[2]保持不变等于next[2]=1序号J123456模式串a b a b a anext[j]011234nextval[j]01第⼆次for循环,j=3,当前序号a的next[3]为1,即第⼀个序号所指向的字符a,a=当前序号a,所以nextval[3]等于nextval[1]=0序号J123456模式串a b a b a anext[j]011234nextval[j]010第三次for循环,j=4,当前序号b的next[4]为2,即第⼆个序号所指向的字符b,b=当前序号b,所以nextval[4]等于nextval[2]=1序号J123456模式串a b a b a anext[j]011234nextval[j]0101就是这样,你可以练练5和6,这⾥直接给出~~序号J123456模式串a b a b a anext[j]011234nextval[j]010104⾄此nextval数组的求法你也应该会了,那么考研要是考了,那么是不是就等于送分给你呢?⼩练习那么你试着来求⼀下这个模式串的next和nextval数组吧~~next[j]nextval[j]⼩练习的答案序号j12345模式串a a a a b next[j]01234 nextval[j]00004。

(完整word版)KMP算法详解

(完整word版)KMP算法详解

KMP字符串模式匹配详解KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法。

简单匹配算法的时间复杂度为O(m*n);KMP匹配算法。

可以证明它的时间复杂度为O(m+n).。

一.简单匹配算法先来看一个简单匹配算法的函数:int Index_BF ( char S [ ], char T [ ], int pos ){/* 若串S 中从第pos(S 的下标0≤pos<StrLength(S))个字符起存在和串T 相同的子串,则称匹配成功,返回第一个这样的子串在串S 中的下标,否则返回-1 */int i = pos, j = 0;while ( S[i+j] != '\0'&& T[j] != '\0')if ( S[i+j] == T[j] )j ++; // 继续比较后一字符else{i ++; j = 0; // 重新开始新的一轮匹配}if ( T[j] == '\0')return i; // 匹配成功返回下标elsereturn -1; // 串S中(第pos个字符起)不存在和串T相同的子串} // Index_BF此算法的思想是直截了当的:将主串S中某个位置i起始的子串和模式串T相比较。

即从j=0 起比较S[i+j] 与T[j],若相等,则在主串S 中存在以i 为起始位置匹配成功的可能性,继续往后比较( j逐步增1 ),直至与T串中最后一个字符相等为止,否则改从S串的下一个字符起重新开始进行下一轮的"匹配",即将串T向后滑动一位,即i 增1,而j 退回至0,重新开始新一轮的匹配。

例如:在串S=”abcabcabdabba”中查找T=” abcabd”(我们可以假设从下标0开始):先是比较S[0]和T[0]是否相等,然后比较S[1] 和T[1]是否相等…我们发现一直比较到S[5] 和T[5]才不等。

KMP算法的应用

KMP算法的应用

KMP算法的应用2. 数据压缩:KMP算法可以用于数据压缩算法中,例如RLE(Run Length Encoding)算法。

RLE算法通过将连续出现的相同字符进行压缩,可以大大减小数据的存储空间。

KMP算法在判断连续字符的出现位置时非常高效,可以帮助提高压缩算法的速度。

3.DNA序列匹配:在生物信息学中,KMP算法可以用于DNA序列的匹配。

DNA序列是由A、C、G、T四种字符组成的序列,KMP算法可以帮助确定DNA序列中是否存在特定的子序列,并计算其出现的位置。

这对于基因分析和生物实验的设计都有重要意义。

4.正则表达式匹配:正则表达式是一种用于匹配字符串的表达式,通常由一系列字符和操作符组成。

KMP算法可以用于实现正则表达式引擎中的字符串匹配功能,例如在引擎中通过正则表达式进行页面的筛选和聚类。

5.图像处理:在图像处理中,KMP算法可以用于图像相似性。

例如,当需要在一张大图中查找与给定小图相似的部分时,KMP算法可以帮助确定小图在大图中的位置,并进行进一步的处理。

6.模式识别:KMP算法在模式识别中也有广泛的应用。

例如,在人脸识别中,KMP算法可以用于查找待识别人脸的特征点,以便进行进一步的识别和比对。

总结来说,KMP算法的应用非常广泛,涉及到字符串匹配、数据压缩、生物信息学、正则表达式、图像处理和模式识别等多个领域。

它通过利用模式串中已经匹配的信息减少匹配过程中的比较次数,从而提高了匹配的效率。

KMP算法的核心思想是使用有限状态自动机(Finite State Machine)来记录模式串与文本串在匹配过程中的关系,从而快速定位匹配的位置。

在实际应用中,KMP算法可以帮助提高程序的性能和效率,减少计算资源的消耗。

数据结构教学中KMP算法解析

数据结构教学中KMP算法解析

数据结构教学中KMP算法解析摘要:模式匹配是字符串的基本运算之一,也是数据结构教学中的难点之一。

分析了模式匹配KMP算法以及算法中next函数的含义,给出了next函数的两种实现方法,有助于在教学实践中帮助学生更好地理解该算法。

关键词:数据结构;模式匹配;KMP算法0引言模式匹配(Patten Matching)是许多计算机应用领域的基础问题,在数据结构中模式匹配是字符串的基本运算之一。

字符串模式匹配指的是,找出特定的模式串在一个较长的字符串中出现的位置。

有两个字符串S和T,字符串S称为目标串,字符串T称为模式串,要求找出模式T在S中的首次出现的位置。

一旦模式T在目标S中找到,就称发生一次匹配。

有些应用可能会要求找出所有的匹配位置<sup>[1]</sup>。

例如,目标串S= 'Shanghai',模式串T= 'gha',则匹配结果为4。

模式匹配的典型算法包括朴素匹配算法、KMP算法和BM算法等,其中KMP算法是效率较高且经典的模式匹配算法之一<sup>[2]</sup>。

在数据结构教学中,由于KMP算法较难理解,课堂讲授往往很难取得好的效果。

本文通过对传统的朴素匹配算法与KMP算法的比较,分析next函数的含义以及实现方法,来帮助理解KMP算法。

1朴素匹配算法在朴素匹配算法中,S和T分别为目标串和模式串,变量i和j 为两个静态指针,分别表示S和T中当前正待比较的字符位置。

算法的基本思想是:第1趟匹配:从S的第1个字符(序号为0)起和T的第一个字符比较之,如果相等,则继续逐个比较后续字符(i++;j++),否则开始下一趟匹配。

新的一趟匹配:i的初值为上一趟的初值+1 ,j的初值为1,如果比较结果相等,则继续逐个比较后续字符,否则开始下一趟匹配。

依次类推,直至某一趟匹配中,T的每个字符依次和S中的一个连续的字符序列相等,则称匹配成功,否则称匹配不成功。

数据结构与算法_桂林电子科技大学中国大学mooc课后章节答案期末考试题库2023年

数据结构与算法_桂林电子科技大学中国大学mooc课后章节答案期末考试题库2023年

数据结构与算法_桂林电子科技大学中国大学mooc课后章节答案期末考试题库2023年1.下面哪种数据结构不是线性结构()参考答案:二叉树2.串S=”myself“,其子串的数目是()参考答案:223.设目标串为‘abccdcdccbaa',模式串为'cdcc',则第()次匹配成功。

参考答案:64.串S='aaab',其next数组为()参考答案:-1 0 1 25.KMP算法相对于BF算法的优点是时间效率高参考答案:正确6.串是一种数据对象和操作都特殊的线性表参考答案:正确7.下面哪个()可能是执行一趟快速排序能够得到的序列参考答案:[41,12,34,45,27] 55 [72,63]8.设主串t的长度为n,模式串p的长度为m,则BF算法的时间复杂度为O(n+m)参考答案:错误9.从一个长度为n的顺序表中删除第i个元素(0 ≤ i≤ n-1)时,需向前移动的元素的个数是()参考答案:n-i-110.对线性表进行二分查找时,要求线性表必须()参考答案:以顺序方式存储,且结点按关键字有序排序11.某线性表中最常用的操作是在最后一个元素之后插入一个元素和删除第一个元素,则采用()存储方式最节省运算时间。

参考答案:仅有尾指针的单循环链表12.最小不平衡子树是指离插入结点最近,且包含不平衡因子结点的子树参考答案:正确13.在单链表中,存储每个结点需有两个域,一个是数据域,另一个是指针域,它指向该结点的( )参考答案:直接后继14.从一个具有n个节点的单链表中查找其值等于x结点时,在查找成功的情况下,需平均比较()个结点参考答案:n/215.对以下单循环链表分别执行下列程序段,说明执行结果中,各个结点的数据域分别是()p = tail→link→link; p→info = tail→info;【图片】参考答案:8,3,6,816.对以下单链表执行如下程序段,说明执行结果中,各个结点的数据域分别是()void fun (Linklist H) //H是带有头结点的单链表{ PNode p,q; p=H->link;H->link=NULL; while (p) { q=p; p=p->link; q->link=H->link; H->link=q; }}【图片】参考答案:8,6,4,217.根据教科书中线性表的实现方法,线性表中的元素必须是()参考答案:相同类型18.若线性表中最常用的操作是存取第i个元素及其前驱和后继元素的值,为了节省时间应采用的存储方式()参考答案:顺序表19.若已知一个栈的入栈序列是1,2,3,…,n,其输出序列为p1,p2,p3,…,pn,若p1=n,则pi为()参考答案:n-i+120.循环队列用数组A[0,m-1]存放其元素值,已知其头尾指针分别是front和rear,则当前队列中的元素个数是()参考答案:(rear-front+m)%m21.已知其头尾指针分别是front和rear,判定一个循环队列QU(最多元素为m)为空的条件是()参考答案:QU—>front= =QU—>rear22.一个队列的入列序列是1,2,3,4,则队列的输出序列是()参考答案:1,2,3,423.已知其头尾指针分别是front和rear,判定一个循环队列QU(最多元素为m)为满的条件是()参考答案:QU—>front= =(QU—>rear+1)%m24.在计算机内实现递归算法时所需的辅助数据结构是( )参考答案:栈25.设循环队列的元素存放在一维数组Q[0‥30]中,队列非空时,front指示队头元素的前一个位置,rear指示队尾元素。

(原创)详解KMP算法

(原创)详解KMP算法

(原创)详解KMP算法KMP算法应该是每⼀本《数据结构》书都会讲的,算是知名度最⾼的算法之⼀了,但很可惜,我⼤⼆那年压根就没看懂过~~~之后也在很多地⽅也都经常看到讲解KMP算法的⽂章,看久了好像也知道是怎么⼀回事,但总感觉有些地⽅⾃⼰还是没有完全懂明⽩。

这两天花了点时间总结⼀下,有点⼩体会,我希望可以通过我⾃⼰的语⾔来把这个算法的⼀些细节梳理清楚,也算是考验⼀下⾃⼰有真正理解这个算法。

什么是KMP算法:KMP是三位⼤⽜:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的。

其中第⼀位就是《计算机程序设计艺术》的作者!!KMP算法要解决的问题就是在字符串(也叫主串)中的模式(pattern)定位问题。

说简单点就是我们平时常说的关键字搜索。

模式串就是关键字(接下来称它为P),如果它在⼀个主串(接下来称为T)中出现,就返回它的具体位置,否则返回-1(常⽤⼿段)。

⾸先,对于这个问题有⼀个很单纯的想法:从左到右⼀个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动⼀位。

这有什么难的?我们可以这样初始化:之后我们只需要⽐较i指针指向的字符和j指针指向的字符是否⼀致。

如果⼀致就都向后移动,如果不⼀致,如下图:A和E不相等,那就把i指针移回第1位(假设下标从0开始),j移动到模式串的第0位,然后⼜重新开始这个步骤:基于这个想法我们可以得到以下的程序:1/**23 * 暴⼒破解法45 * @param ts 主串67 * @param ps 模式串89 * @return如果找到,返回在主串中第⼀个字符出现的下标,否则为-11011*/1213public static int bf(String ts, String ps) {1415char[] t = ts.toCharArray();1617char[] p = ps.toCharArray();1819int i = 0; // 主串的位置2021int j = 0; // 模式串的位置2223while (i < t.length && j < p.length) {2425if (t[i] == p[j]) { // 当两个字符相同,就⽐较下⼀个2627 i++;2829 j++;3031 } else {3233 i = i - j + 1; // ⼀旦不匹配,i后退3435 j = 0; // j归03637 }3839 }4041if (j == p.length) {4243return i - j;4445 } else {4647return -1;4849 }5051 }上⾯的程序是没有问题的,但不够好!(想起我⾼中时候数字⽼师的⼀句话:我不能说你错,只能说你不对~~~)如果是⼈为来寻找的话,肯定不会再把i移动回第1位,因为主串匹配失败的位置前⾯除了第⼀个A之外再也没有A了,我们为什么能知道主串前⾯只有⼀个A?因为我们已经知道前⾯三个字符都是匹配的!(这很重要)。

罗文劼《数据结构与算法》第4版-第3章课后习题参考答案

罗文劼《数据结构与算法》第4版-第3章课后习题参考答案

第3章线性结构的扩展1.选择题(1)B (2)A (3)DAB (4)CCC (5)C2.判断题(1)Ⅹ(2)√(3)√(4)√(5)Ⅹ(6)Ⅹ(7)Ⅹ(8)Ⅹ(9)Ⅹ(10)Ⅹ3.简答题1.KMP算法较朴素的模式匹配算法有哪些改进?【解答】KMP算法主要优点是主串指针不回溯。

当主串很大不能一次读入内存且经常发生部分匹配时,KMP 算法的优点更为突出。

2.设字符串S=‘aabaabaabaac',P=‘aabaac'。

(1)给出S和P的next值和nextval值;(2)若S作主串,P作模式串,试给出利用KMP算法的匹配过程。

【解答】(1)S的next与nextval值分别为012123456789和002002002009,p的next与nextval值分别为012123和002003。

(2)利用BF算法的匹配过程:利用KMP算法的匹配过程:第一趟匹配:aabaabaabaac 第一趟匹配:aabaabaabaacaabaac(i=6,j=6) aabaac(i=6,j=6)第二趟匹配:aabaabaabaac 第二趟匹配:aabaabaabaacaa(i=3,j=2) (aa)baac第三趟匹配:aabaabaabaac 第三趟匹配:aabaabaabaaca(i=3,j=1) (成功) (aa)baac第四趟匹配:aabaabaabaacaabaac(i=9,j=6)第五趟匹配:aabaabaabaacaa(i=6,j=2)第六趟匹配:aabaabaabaaca(i=6,j=1)第七趟匹配:aabaabaabaac(成功) aabaac(i=13,j=7)3.考虑对KMP算法能否再做改进。

【解答】4.说明一维数组与有序表的异同。

【解答】数组:数组是由类型名、标识符和维数组成的符合数据类型,类型名规定了存放在数组中的元素的类型,而维数则指数组中包含的元素个数。

线性表:(亦作有序表)是最基本、最简单、也是最常用的一种数据结构。

kmp算法详解

kmp算法详解

引记此前一天,一位MS的朋友邀我一起去与他讨论快速排序,红黑树,字典树,B树、后缀树,包括KMP算法,唯独在讲解KMP算法的时候,言语磕磕碰碰,我想,原因有二:1、博客内的东西不常回顾,忘了不少;2、便是我对KMP算法的理解还不够彻底,自不用说讲解自如,运用自如了。

所以,特再写本篇文章。

由于此前,个人已经写过关于KMP算法的两篇文章,所以,本文名为:KMP算法之总结篇。

本文分为如下六个部分:1. 第一部分、再次回顾普通的BF算法与KMP算法各自的时间复杂度,并两相对照各自的匹配原理;2. 第二部分、通过我此前第二篇文章的引用,用图从头到尾详细阐述KMP算法中的next数组求法,并运用求得的next数组写出KMP算法的源码;3. 第三部分、KMP算法的两种实现,代码实现一是根据本人关于KMP算法的第二篇文章所写,代码实现二是根据本人的关于KMP算法的第一篇文章所写;4. 第四部分、测试,分别对第三部分的两种实现中next数组的求法进行测试,挖掘其区别之所在;5. 第五部分、KMP完整准确源码,给出KMP算法的准确的完整源码;6. 第六步份、一眼看出字符串的next数组各值,通过几个例子,让读者能根据字符串本身一眼判断出其next数组各值。

力求让此文彻底让读者洞穿此KMP算法,所有原理,来龙去脉,让读者搞个通通透透(注意,本文中第二部分及第三部分的代码实现一的字符串下标i 从0开始计算,其它部分如第三部分的代码实现二,第五部分,和第六部分的字符串下标i 皆是从1开始的)。

在看本文之前,你心中如若对前缀和后缀这个两个概念有自己的理解,便最好了。

有些东西比如此KMP算法需要我们反复思考,反复求解才行。

个人写的关于KMP算法的第二篇文章为:六(续)、从KMP算法一步一步谈到BM算法;第一篇为:六、教你初步了解KMP算法、updated(文末链接)。

ok,若有任何问题,恳请不吝指正。

多谢。

第一部分、KMP算法初解1、普通字符串匹配BF算法与KMP算法的时间复杂度比较KMP算法是一种线性时间复杂的字符串匹配算法,它是对BF算法(Brute-Force,最基本的字符串匹配算法的)改进。

KMP算法

KMP算法

从头到尾彻底理解KMP作者:July时间:最初写于2011年12月,2014年7月21日晚10点全部删除重写成此文,随后的半个多月不断反复改进。

后收录于新书《编程之法:面试和算法心得》第4.4节中。

1. 引言本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP,思路混乱导致写也写得混乱。

所以一直想找机会重新写下KMP,但苦于一直以来对KMP的理解始终不够,故才迟迟没有修改本文。

然近期因开了个算法班,班上专门讲解数据结构、面试、算法,才再次仔细回顾了这个KMP,在综合了一些网友的理解、以及算法班的两位讲师朋友曹博、邹博的理解之后,写了9张PPT,发在微博上。

随后,一不做二不休,索性将PPT 上的内容整理到了本文之中(后来文章越写越完整,所含内容早已不再是九张PPT 那样简单了)。

KMP本身不复杂,但网上绝大部分的文章(包括本文的2011年版本)把它讲混乱了。

下面,咱们从暴力匹配算法讲起,随后阐述KMP的流程步骤、next 数组的简单求解递推原理代码求解,接着基于next 数组匹配,谈到有限状态自动机,next 数组的优化,KMP的时间复杂度分析,最后简要介绍两个KMP的扩展算法。

全文力图给你一个最为完整最为清晰的KMP,希望更多的人不再被KMP折磨或纠缠,不再被一些混乱的文章所混乱。

有何疑问,欢迎随时留言评论,thanks。

2. 暴力匹配算法假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢?如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P 匹配到 j 位置,则有:如果当前字符匹配成功(即S[i] == P[j]),则i++,j++,继续匹配下一个字符;如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0。

相当于每次匹配失败时,i 回溯,j 被置为0。

理清楚了暴力匹配算法的流程及内在的逻辑,咱们可以写出暴力匹配的代码,如下:[cpp]view plaincopyprint?1.int ViolentMatch(char* s, char* p)2.{3.int sLen = strlen(s);4.int pLen = strlen(p);5.6.int i = 0;7.int j = 0;8.while (i < sLen && j < pLen)9.{10. if (s[i] == p[j])11. {12. //①如果当前字符匹配成功(即S[i] == P[j]),则i++,j++13. i++;14. j++;15. }16. else17. {18. //②如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 019. i = i - j + 1;20. j = 0;21. }22. }23. //匹配成功,返回模式串p在文本串s中的位置,否则返回-124. if (j == pLen)25. return i - j;26. else27. return -1;28.}举个例子,如果给定文本串S“BBC ABCDAB ABCDABCDABDE”,和模式串P“ABCDABD”,现在要拿模式串P去跟文本串S匹配,整个过程如下所示:1.S[0]为B,P[0]为A,不匹配,执行第②条指令:“如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0”,S[1]跟P[0]匹配,相当于模式串要往右移动一位(i=1,j=0)2. S[1]跟P[0]还是不匹配,继续执行第②条指令:“如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0”,S[2]跟P[0]匹配(i=2,j=0),从而模式串不断的向右移动一位(不断的执行“令i = i - (j - 1),j = 0”,i 从2变到4,j一直为0)3. 直到S[4]跟P[0]匹配成功(i=4,j=0),此时按照上面的暴力匹配算法的思路,转而执行第①条指令:“如果当前字符匹配成功(即S[i] == P[j]),则i++,j++”,可得S[i]为S[5],P[j]为P[1],即接下来S[5]跟P[1]匹配(i=5,j=1)4. S[5]跟P[1]匹配成功,继续执行第①条指令:“如果当前字符匹配成功(即S[i] == P[j]),则i++,j++”,得到S[6]跟P[2]匹配(i=6,j=2),如此进行下去5. 直到S[10]为空格字符,P[6]为字符D(i=10,j=6),因为不匹配,重新执行第②条指令:“如果失配(即S[i]! = P[j]),令i = i - (j - 1),j = 0”,相当于S[5]跟P[0]匹配(i=5,j=0)6. 至此,我们可以看到,如果按照暴力匹配算法的思路,尽管之前文本串和模式串已经分别匹配到了S[9]、P[5],但因为S[10]跟P[6]不匹配,所以文本串回溯到S[5],模式串回溯到P[0],从而让S[5]跟P[0]匹配。

KMP算法详解

KMP算法详解

KMP算法详解写在前⾯:欢迎转载,转载请在⽂章显眼处注明出处:https:///grcyh/p/10519791.html起源所谓KMP(看⽑⽚233⼿动滑稽)算法,就是⼀种改进的算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此⼈们称它为————操作(简称KMP算法)。

KMP算法的关键是利⽤匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的⽬的。

具体实现就是实现⼀个next()函数,函数本⾝包含了模式串的局部匹配信息。

O(m+n)。

——百度百科前置知识:输⼊输出数组for循环模式串匹配的概念:模式串匹配,就是给定⼀个需要处理的⽂本串和⼀个需要在⽂本串中搜索的模式串,查询在该⽂本串中(⼀般⽂本串应远⼤于模式串),模式串的是否出现过,出现的次数和出现的位置等。

朴素算法:⾸先要理解,朴素的单模式串匹配⼤概就是枚举每⼀个⽂本串元素,然后从这⼀位开始不断向后⽐较,每次⽐较失败之后都要从头开始重新⽐对,那么如果模式串和⽂本串是类似于这样的:模式串aaaab,⽂本串是aaabaaabaaab,如果是这样的话,我们设模式串长度为m,⽂本串长度为n,那么朴素的暴⼒算法就会被卡成O(nm),于是就有了那三个家伙⼤佬的KMP(然⽽并不认识他们是谁233),下⾯我们就要讲KMP了,准备好!KMP:在朴素算法中,我们每次匹配失败都不得不放弃之前所有的匹配进度,因此时间复杂度很⾼,⽽KMP算法的精髓就在于每次匹配失败之后不会从模式串的开头进⾏匹配,⽽是根据已知的匹配数据,跳回模式串⼀个特定的位置继续进⾏匹配,⽽且对于模式串的每⼀位,都有⼀个唯⼀的“特定跳回位置”,从⽽节约时间。

⽐如我们考虑⼀组样例:模式串:abcab⽂本串:abcacababcab⾸先,前四位按位匹配成功,遇到第五位不同,⽽这时,我们选择将模式串向右移三位,或者可以理解为移动到模式串中与失配字符相同的那⼀位。

基于MATLAB的数据结构与算法_线性表部分

基于MATLAB的数据结构与算法_线性表部分

举例:建立一个类
下面用一个简单的例子类介绍一些类如何使 用。
定义一个名为list的类,
它有两个数据成员x和y, 希望通过一个成员函数prod()来获取x和y的乘积。
举例:建立一个类

类名: list 成员变量:x,y 成员函数: list:构造函数 display:显示函数 get:取值函数 set:赋值函数 prod:计算函数
现在就来建立它。
举例:建立一个类
第一步:
(1) 在工作目录上建立一个子目录(以笔者的习惯为例): cd E:\MyProgram\matlab7\chap4 mkdir @list 类名前面要加上一个字符'@’,对于这样形式的目录里所有保 存的M文件,MATLAB都认为是类的成员函数。
举例:建立一个类
举例:创建类

类成员变量的赋值 本例中,类的成员变量是在构造函数中赋值的。MATLAB中,类成员 变量都是private的,必须在成员函数中访问,因此就不能箱struct那样, 用d.x和d.y等形式访问其成员变量了。访问时编个专门的成员函数get 就行了。另外,成员函数的调用跟普通的函数一样。注意在get和set 函数中,成员变量是以字符串的形式指定的,要通过字符串比较的办 法进行区分,然后对输出变量进行赋值。本例中的set函数支持同时对 两个成员变量赋值,因此用到了不定长输入产生表varargin,例如: d = set(d,'x',12) % 只对其中一个成员变量赋值 list class: x=12 y=22 d = set(d,'x',23,'y',34) % 同时对两个成员变量赋值 list class: x=23 y=34
定义类的好处

K M P 算 法 详 解

K M P 算 法 详 解

KMP算法详解-----BY Matrix67如果机房马上要关门了,或者你急着要和MM约会,请直接跳到第六个自然段。

?我们这里说的KMP不是拿来放电影的(虽然我很喜欢这个软件),而是一种算法。

KMP算法是拿来处理字符串匹配的。

换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串)。

比如,字符串A="I'mmatrix67",字符串B="matrix",我们就说B是A的子串。

你可以委婉地问你的MM:“假如你要向你喜欢的人表白的话,我的名字是你的告白语中的子串吗?”?解决这类问题,通常我们的方法是枚举从A串的什么位置起开始与B匹配,然后验证是否匹配。

假如A串长度为n,B串长度为m,那么这种方法的复杂度是O (mn)的。

虽然很多时候复杂度达不到mn (验证时只看头一两个字母就发现不匹配了),但我们有许多“最坏情况”,比如,A="aaaaaaaaaaaaaaaaaaaaaaaaaab",B="aaaaaaaab"。

我们将介绍的是一种最坏情况下O(n)的算法(这里假设 m=n),即传说中的KMP算法。

?之所以叫做KMP,是因为这个算法是由Knuth、Morris、Pratt三个提出来的,取了这三个人的名字的头一个字母。

这时,或许你突然明白了AVL 树为什么叫AVL,或者Bellman-Ford为什么中间是一杠不是一个点。

有时一个东西有七八个人研究过,那怎么命名呢?通常这个东西干脆就不用人名字命名了,免得发生争议,比如“3x+1问题”。

扯远了。

?个人认为KMP 是最没有必要讲的东西,因为这个东西网上能找到很多资料。

但网上的讲法基本上都涉及到“移动(shift)”、“Next函数”等概念,这非常容易产生误解(至少一年半前我看这些资料学习KMP时就没搞清楚)。

在这里,我换一种方法来解释KMP算法。

?假如,A="abababaababacb",B="ababacb",我们来看看KMP是怎么工作的。

《KMP 字符串模式匹配算法》教学课例

《KMP 字符串模式匹配算法》教学课例

《KMP字符串模式匹配算法》教学课例程玉胜安庆师范学院计算机与信息学院KMP字符串模式匹配是数据结构课程中一个重要的知识点,也是一个难点(学过KMP 算法的同学100%认为:KMP是数据结构课程中最难的部分)。

为了消除他们对KMP算法学习的恐惧心理,激发他们的学习兴趣,调动其积极性,显得尤为重要。

基于以上,我们根据学生的认知特点和接受水平,对教材内容进行了重新构建,并按照数据结构中“时间复杂度”概念,增加了不同模式匹配算法的运行时间,动态逼真的显示了算法的“时间”性能,获得了较好的教学效果。

一、教学目标知识目标:让学生了解KMP算法应用的普遍性。

如:在目前众多的文字处理软件中得到广泛应用,如Microsoft Word中的“查找”或“替换”操作。

而这种操作实现的机制,同学们特别是计算机专业的学生很少去想过。

能力目标:要求学生体验一个完整的抽象数据类型(ADT)的实现方法和过程,并学会判断、计算算法优劣的方法。

价值目标:消除恐怖的学习心态,让学生感悟数据结构算法实际应用价值,从而激发学习的兴趣,形成积极主动式学习的态度。

二、教材分析使用教材是清华大学严蔚敏教授并由清华大学出版社出版的《数据结构(C语言版)》,该教材难度较大,其实验方法特别是ADT方法在教材中介绍较少,而且KMP算法更是从理论分析的角度介绍了匹配算法和next的计算,自学难度很大;虽然该节知识点属于“**(表示难度较大,可以不讲)”,但是其又是考研的一个热点,所以我们又不得不讲。

三、教学重点、难点教学重点:KMP算法中的next和改进的nextval计算教学难点:KMP算法中如何计算next值四、教具准备卡片:多个字符串,字符串指针强力磁吸:6个五、互动式教学过程教学内容教师活动学生活动目标状态创设情境引入课题目前的众多软件中,“查找”、“替换”等操作实现方法,要求学生举例。

给出一篇word文档完成在上述文档中从当前位置向后查找“计算机”或者向前查找“计算机”字符串的方法。

数据结构 KMP算法

数据结构 KMP算法

问题的进一步分析:
S=“abcabeacadaadadasfsf” T=“abcabc” 上述第一轮比较在i j都为6时失败,传统的方案 是j=1,i=2进行下一轮,及如下: S=“abcabeacadaadadasfsf”
T=“abcabc” 而KPM告诉我们,应该这样: S=“abcabeacadaadadasfsf”
T=“abcde” 上式中,当i,j都为5时,比较失败,其时iห้องสมุดไป่ตู้回 溯,j从1开始,进行如下比较:
S=“abcdabcabababcde”
T=“abcde”
上例是特例,模式任一子串不是其它串的子串,即 字符互不相等。事实上:
1、我们可以相对容易的找出模式自身的特征;
2、我们依据刚比较的这一轮,结合模式内在特征 来找出模式回溯的位置
Times=5+1+3+1+1+5=16
KMP算法的思想是发现出模式内在的关联, 减少回溯:
极端的例子
目标 S=“abcdabcabababcde” 模式 T=“abcde” 可以想见,由于模式T所有字符都不相等,所
以如果某次比较失败后,目标指针根本不 需要回溯!
???
目标 S=“abcdabcabababcde” 模式 T=“abcde” 设目标的指针为i,模式的当前指针为j S=“abcdabcabababcde”
next(j) 0
1
1
1
2
2
3
2
3
KMP算法的思想就是:假设指针i ,j分别为主 串和子串不匹配所在的位置, 则i不变,j退 到next(j)所在的位置再进行比较,如相等, i,j各自增1,否则,当前的j再一次退到 next(j),直至j=1时,此时,i增1,子串则从头 开始

顺序表、链表、KMP算法-数据结构报告

顺序表、链表、KMP算法-数据结构报告

目录需求分析-------------------------------------------------P3 概要设计-------------------------------------------------P4 详细设计-------------------------------------------------P9 调试分析-------------------------------------------------P11 测试结果-------------------------------------------------P11 课程设计总结---------------------------------------------P15 参考文献-------------------------------------------------P16 附录------------------------------------------------------P16一:需求分析:顺序表的插入、删除、合并等操作:涉及顺序表的创建、插入、删除、查找、合并、显示等。

采用数组作为顺序表的结构,定义一个MAXSIZE 作为数组的最大长度。

从键盘接收用户输入的基本数据类型(这里以char为例,也可以是int等其他类型)为例演示方便,系统自带一个已经含有元素的顺序表。

然后接收用户输入指令进行相应的操作。

插入演示时,要求用户输入插入的字符串和要插入的位置;删除演示时要求用户输入要删除的长度和起始位置;合并操作演示时,要求用户输入一个字符串用来建立新的顺序表,然后两个顺序表合并并输出新的顺序表。

链表的查找、删除、计数、输出等功能以及有序链表的合并:涉及链表的创建、删除、查找、合并、显示等。

需要动态分配内存,用指针连接各节点。

先自定义一个ListNode节点用户存储数据和指针。

为了演示方便,系统依然自带了一个创建好并且含有若干元素的链表,用户可以在此基础上进行操作。

基于matlab的数据结构与算法kmp

基于matlab的数据结构与算法kmp
i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B=ababacb
j=1234567 显然是求一个最长的以i为末尾的后缀要与B的前缀匹配。
由于A[i-j+ 1..i]与B[1..j]完全相等,故令j’=next[ j]即可保 证此性质保留
KMP算法的运行过程
i = 1 2 3 4 5 6 7 8 9 ……
A=abababaabab…
B=ababacb
j=1234567
i = 1 2 3 4 5 6 7 8 9 ……
A=abababaabab…

B=ababacb
j ‘= 1 2 3 4 5 6 7
KMP算法的运行过程
需要注意的是i并没有动,改变的只是j的值 如果改变j的值后a[i+1]仍不等于b[ j+1]的话,继
在i使 xi+k=ak(k=1,2,…m)时,认为text与 模式串匹配,当然text也可能与模式串有多 处匹配
例如:text: abcabca, s:abc 则text与s匹 配的位置有3和6
KMP算法
作为一种无回溯的算法,它是高效的,待 会儿你将看到它的时间复杂度为O(m+n), 空间复杂度也为O(m+n)
基于MATLAB 《数据结构与算法》
延边大学 信息管理专业(13级) 崔基哲
MATLAB编程之基础算法
KMP模式匹配算法
串的模式匹配算法
一、基本概念 1、模式匹配(定位)
设有主串S和子串T(将S称为目标串,将T称为模式 串),在主串S中,从位置start开始查找,如若在主 串S中找到一个与子串T相等的子串,则返回T的第一 个字符在主串中的位置,否则返回-1。 2、算法目的
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。


i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B=ababacb j=1234567 显然是求一个最长的以i为末尾的后缀要与B的前缀匹配。 由于A[i-j+ 1..i]与B[1..j]完全相等,故令j‟=next[j]即可保证此 性质保留
KMP算法的运行过程

执行结果验证
KMP算法的运行过程


我们用两个指针i和j分别表示,A[i-j+ 1..i]与B[1..j]完全相等。 也就是说,i是不断增加的,随着i的增加j相应地变化,且j 满足以A[i]结尾的长度为j的字符串正好匹配B串的前 j个字 符(j当然越大越好),现在需要检验A[i+1]和B[j+1]的关 系。 如果a[i+1]==b[j+1],i和j各加1,什么时候j==m,就说B是A 的子串(B串已经4 5 6 7 8 9 …… A=abababaabab… B=ababacb j=1234567 i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B=ababacb j „= 1 2 3 4 5 6 7
KMP算法的运行过程



需要注意的是i并没有动,改变的只是j的值 如果改变j的值后a[i+1]仍不等于b[j+1]的话,继续 改变j值直到a[i+1]==b[j+1]或者j=0 j=0表示i+1前面无论怎么匹配都不能使 a[i+1]==b[j+1],只好让a[i+1]与b[j+1]单独匹配 还是上一个例子,再演示一下
KMP算法的运行过程

i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B= ababacb j= 1234567

终于,A[8]=B[1],i变为8,j为1
KMP算法的运行过程

i = 1 2 3 4 5 6 7 8 9 …… A=abababadbab… B= ababacb j= 1234567 事实上,有可能j到了0仍然不能满足A[i+1]=B[j+1](比如 A[8]=“d”时)。因此,准确的说法是,当j=0了时,我们直 接增加i值但忽略j直到出现A[i]=B[1]为止。
KMP算法的运行过程



i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B= ababacb j= 1234567 当i=6,j=5时,a[i+1]!=b[j+1],故令 j=next[5]=3
KMP算法的运行过程

i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B= ababacb j= 1234567
KMP算法的运行过程

如果a[i+1]!=b[j+1],这时候怎么办? i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B=ababacb j=1234567 j=5时,a[i+1]!=b[j+1],我们要把j改成比它小的值j„。改成 多少合适呢?
KMP算法的运行过程
基于MATLAB 《数据结构与算法》
延边大学 信息管理专业(13级) 崔基哲
MATLAB编程之基础算法
KMP模式匹配算法
串的模式匹配算法 一、基本概念 1、模式匹配(定位) 设有主串S和子串T(将S称为目标串,将T称为模式 串),在主串S中,从位置start开始查找,如若在主 串S中找到一个与子串T相等的子串,则返回T的第一 个字符在主串中的位置,否则返回-1。 2、算法目的 确定主串中所含子串第一次出现的位置(定位) 3、算法种类 KMP算法
3
KMP模式匹配算法

它是:在一个长字符串中匹配一 个短子串的无回溯算法。
定义


s: 模式串 , m: 模式串的长度 text: 要匹配的字符串, n:text的长度 设text: x1,x2,…xn , s: a1,a2,…am, 则当存在i 使 xi+k=ak(k=1,2,…m)时,认为text与模式 串匹配,当然text也可能与模式串有多处匹 配 例如:text: abcabca, s:abc 则text与s匹配的 位置有3和6


i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B=ababacb j=1234567 记住,我们要保持A[i-j+ 1..i]与B[1..j]完全相等,因而j‟是最 大的数使a[i-j‟+1..i]与B[1..j‟]完全相等.
KMP算法的运行过程


此时i=6,j=3 仍不满足a[i+1]==b[j+1],故继 续减小j,使j=next[3]=1
KMP算法的运行过程

i = 1 2 3 4 5 6 7 8 9 …… A=abababaabab… B= ababacb j= 1234567

此时i=6,j=1 仍不满足a[i+1]==b[j+1],故继 续减小j,使j=next[1]=0
KMP算法


作为一种无回溯的算法,它是高效的,待 会儿你将看到它的时间复杂度为O(m+n), 空间复杂度也为O(m+n) 而且,它很容易理解,代码也很短
定义


next: 为对应模式串的数组 设字符串为 s1s2s3...sm ,其中s1,s2,s3 ,... si,... sm均是字符,则next[i]=m,当 且仅当满足如下条件:字符串s1s2...sm equals 字符串s(i-m+1)...si-1 si 并且 s1s2...sm s(m+1) unequals s(i-m) s(im+1)...si-1 si。 通俗地讲,next[i]保存了以s[i]为结尾的后缀 与模式串前缀的最长匹配数。
相关文档
最新文档