离开学校已经多年了,早已经不再抚弄那些陈旧的书籍。
周末,深圳的天气阴沉,老天这段时间总是很乐意显摆,动不动就给深圳人民来次几十年一遇的暴雨,似乎要把一年的雨水全部在这些天下完似的。
所以呆在家里面看电视,上网,实在也无聊。随手翻开大学时候的(数据结构,还留着啊,当初刚出来的时候总没有底气,总希望能够随时充电用)。看到了字符串的模式匹配一章。突然发现KMP算法是如此的经典。故记之。。。
在提KMP的经典之前,首先要提基本的模式匹配算法:
所谓模式匹配,简单点说就是对两字符串进行匹配,找出一个字符串在另一个字符串中的位置。
基本的模式匹配是这样的:
假设有字符串
S=S1S2......SN(由于为了算法效率的需要,所以一般都把S[0]保存S的长度)
P=P1P2......PM(同上)
其中(M<N),要求返回P在S中出现的位置。
所以算法要点如下:
假设从S中i点开始扫描(也就是从S[i]开始,此时用一个变量k=i),顺序比较S[i]和P[1],S[i+1]和P[2]。这样,当P进行到第j个字符也就是P[j]的时候,发现S[i+j-1]和P[j]不匹配,那么需要把S的指针i回朔到S起始的下一个字符也就是k+1继续比较。
如图:
以上就是模式匹配的基本算法,这种算法对于大多数的匹配来说基本是O(N+M)的时间复杂度。
但是对于如下的字符串:
S=0000000000000000000000000000001
P=000001
这种字符串来说,每次匹配失败都是在P到最后一个字符也就是j=M的时候,此时S的指针又必须回朔,导致大量的匹配。此时的时间复杂度是O(N*M)。
所以基本算法的时间复杂度是O(N*M)。当然了,对于大多数的匹配是不会有这么高的时间复杂度的,所以这种算法现在也在广泛使用,因为简单。
为了解决上述的问题,KMP算法被发现。
KMP算法的思想如下。匹配过程中,出现不匹配时,S的指针不进行回朔(原地不动),将P尽可能地向后移动一定的距离,再进行匹配。
如图:
从上图中我们看到,当S移动到i,P到j的时候失配。这时候i不回朔,而只是将P向前移动尽可能的距离,继续比较。
假设,P向右移动一定距离后,第k个字符P[k]和S[i]进行比较。
此时如上图,当P[j]和S[i]失配后,i不动,将P前移到K,让P[k]和S[i]继续匹配。现在的关键是K的值是多少?
通过上图,我们发现,因为黄色部分表示已经匹配了的结果(因为是到了S[i]和P[j]的时候才失配,所以Si-j+1Si-j+2…Si-1 = P1P2…Pj-1,见黄色的部分)。所以有:
1、Si-k+1Si-k+2…Si-1 = Pj-k+1Pj-k+2…Pj-1。
所以当P前移到K时,有:
2、Si-k+1Si-k+2…Si-1 = P1P2…Pk-1。
通过1,2有
Pj-k+1Pj-k+2…Pj-1 = P1P2…Pk-1。
呵呵,此时我们的任务就是求这个k值了。。。
理解了这一点之后,终于能够发现此算法的经典了。
分享到:
相关推荐
在实际应用中,BF 算法和 KMP 算法各有其优缺。BF 算法简单易实现,但时间复杂度较高;KMP 算法效率更高,但实现起来相对复杂。因此,在选择字符串匹配算法时,需要根据实际情况进行选择。 BF 算法和 KMP 算法都是...
KMP算法是一种改进的字符串匹配算法,由Donald Knuth、Morris和Frank Pratt共同提出,其主要特点是在匹配过程中能够避免不必要的字符比较,从而提高搜索效率。 KMP算法的核心思想是构建一个部分匹配表(也称为失败...
KMP算法,全称为Knuth-Morris-Pratt算法,是一种在字符串中寻找子串的高效搜索算法。它由D.E. Knuth、V. Morris和J.H. Pratt三位学者于1970年提出,主要用于解决模式匹配问题。传统的KMP算法避免了不必要的字符比较...
模式匹配的KMP算法的主要思想是对目标串进行预处理,生成一个辅助数组next[],该数组记录了模式串中每个字符的最长末尾公共子串的长度。然后,通过比较目标串和模式串,根据next[]数组中的信息,快速地找到模式串在...
在计算机科学领域,字符串匹配是常见的操作之一,其中KMP算法(Knuth-Morris-Pratt算法)因其高效性而被广泛使用。KMP算法由Donald Knuth、James H.Morris以及Vaughan Pratt共同发明,它是一种在主字符串中查找模式...
在提供的压缩包文件中,"KMP算法"很可能包含了实现KMP算法的代码,以及可能的测试用例和改进版本。改进优化可能涉及减少计算部分匹配表的时间复杂度,或者提高算法在特定情况下的效率。通过阅读和理解代码,可以深入...
KMP算法的实现主要基于部分匹配表(Partial Match Table,也称为失配表),它记录了模式串中每个字符前缀和后缀的最大公共长度。当模式串在文本串中比较时遇到不匹配的情况,算法会根据失配表来决定下一次比较时模式...
为了实现上述逻辑,KMP算法引入了一个重要的辅助数组——Next数组,用于记录模式串中每个位置的最佳匹配起点。Next数组的定义如下: - 对于模式串`P`中的每一个位置`j`,`Next[j]`表示模式串`P`中以`p(j)`结束的...
KMP算法的主要优势在于其高效性。由于它能够在模式串不匹配时利用已有的部分匹配信息,避免了不必要的比较,从而大大提高了搜索速度。在处理大规模文本数据时,这种效率的提升尤为重要。 #### 结论 KMP算法是一种...
具体来说,当主串与模式串某处失配时,KMP算法会根据预先计算出的模式串的部分匹配表(通常称为`next`数组),确定模式串应该移动到的位置,而无需让主串指针回溯,这大大减少了不必要的比较次数。 #### 部分匹配表...
本文将详细讨论KMP算法的原理,并着重探讨其在图形界面中的实现。 KMP算法的核心在于构造一个部分匹配表(也称为失配表),它记录了模式串中每个字符之前的所有前缀和后缀的最大公共长度。通过这个表,KMP算法可以...
KMP算法的核心是next数组的计算,next数组是模式串的前缀表,它记录了模式串的各个前缀的最长相等后缀的长度。通过next数组,可以快速地跳过不匹配的字符,从而提高模式匹配的效率。 二、KMP算法的C语言实现 下面...
KMP(Knuth-Morris-Pratt)算法是一种在文本串中查找子串的高效算法,主要用于字符串匹配问题。...在实际编程中,KMP算法常用于文本处理、数据搜索等领域,尤其在处理大规模数据时,其性能优势更为显著。
这个“kmp.rar”压缩包包含了一个C++实现的KMP算法以及Hirschberg算法的源码,这些资源对于理解和应用字符串搜索算法非常有帮助。 KMP算法的核心在于构造一个“部分匹配表”(也称为“失败函数”或“前缀后缀表”)...
在 KMP 算法中,使用 next 数组来记录模式串 T 中每个字符的模式函数值。next[i] 表示模式串 T 中从 0 到 i 的子串和模式串 T 的前缀的最长公共后缀的长度。 KMP 算法的时间复杂度为 O(m+n),远远优于简单匹配算法...
KMP算法避免了模式串在匹配过程中不必要的字符比较,通过构建一个部分匹配表(next数组)来提高效率。 在C语言的实现中,KMP算法通常分为以下几个步骤: 1. **构造部分匹配表**:这部分由`kmp_init`函数完成。部分...
KMP算法的核心是构造一个“部分匹配表”(也称为“失败函数”或“跳跃表”),这个表记录了当模式串中的某个字符与文本串不匹配时,应该将模式串如何向右移动以继续匹配。这样可以避免回溯,提高效率。 ### 部分...
KMP算法的核心是构建一个“部分匹配表”(也称为“失败指针”或“前缀函数”),它记录了子字符串的每一个前缀和后缀的最大公共长度。通过这个表,我们可以知道当子字符串的某个字符与主字符串中的字符不匹配时,...
《算法分析与设计:KMP算法的字符串匹配优化》 KMP算法,全称为Knuth-Morris-Pratt算法,是计算机科学中一种用于字符串匹配的高效算法。它避免了在进行比较时出现的不必要的回溯,从而显著提高了匹配效率。在给定的...