kmp算法流程
kmp算法原理
kmp算法原理KMP算法(Knuth-Morris-Pratt算法)是一种用于快速搜索字符串中某个模式字符串出现位置的算法,由Knuth, Morris 和 Pratt于1977年提出。
KMP算法的工作方式如下:首先,给定一个主串S和一个模式串P,KMP算法的第一步就是先构造一个新的模式串P,其中的每一项存储着P中每一个字符前面由不同字符串组成的最长前缀和最长后缀相同的子串。
接着,在S中寻找P,它会从S的第一个字符开始,如果匹配上,就继续比较下一个字符,如果不匹配上,就根据P中相应位置上保存的信息跳到特定位置,接着再开始比较,如此不断循环下去,直到从S中找到P为止。
KMP算法的思路特别巧妙,比较效率很高,它的复杂度为O(m+n),其中m为主串的长度,n为模式串的长度。
它取代了以前的暴力搜索算法,极大地提高了程序的性能。
KMP算法的实现过程如下:(1)首先确定模式串P的每一个字符,构造模式串P的next数组:next[i]存储P中第i个字符之前最长相同前缀和后缀的长度(P中第i个字符之前最长相同前缀和后缀不包括第i个字符);(2)接着从S中的第一个字符开始比较P中的每一个字符,如果字符不匹配,则采用next数组中保存的信息跳到特定位置,而不是暴力比较,以此不断循环,直到从S中找到P为止。
KMP算法是由Don Knuth, Vaughan Pratt和James Morris在1977年提出的。
它的思想是利用之前遍历过的P的信息,跳过暴力比较,可以把字符串搜索时间从O(m×n)降低到O(m+n)。
KMP算法在很多领域有着重要的应用,如文本编辑,模式匹配,编译器设计与多项式字符串匹配等等,都是不可或缺的。
KMP讲解
有了覆盖函数,那么实现kmp算法就是很简单的了,我们的原则还是从左向右匹配,但是当失配发生时,我们不用把target_index向回移动,target_index前面已经匹配过的部分在pattern自身就能体现出来,只要动pattern_index就可以了。
当发生在j长度失配时,只要把pattern向右移动j-overlay(j)长度就可以了。
说了这么半天那么这种方法是什么呢,这种方法是就大名鼎鼎的确定的有限自动机(Deterministic finite state automaton DFA),DFA可识别的文法是3型文法,又叫正规文法或是正则文法,既然可以识别正则文法,那么识别确定的字串肯定不是问题(确定字串是正则式的一个子集)。对于如何构造DFA,是有一个完整的算法,这里不做介绍了。在识别确定的字串时使用DFA实在是大材小用,DFA可以识别更加通用的正则表达式,而用通用的构建DFA的方法来识别确定的字串,那这个overhead就显得太大了。
{
index = overlay_value[index];
}
if(pattern[index+1]==pattern[i])
{
overlay_value[i] = index +1;
KMP 算法可在O(n+m)时间内完成全部的串的模式匹配工作。
ok,最后给出KMP算法实现的c++代码:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int kmp_find(const string& target,const string& pattern)
kmp算法流程
kmp算法流程
KMP算法是一种字符串匹配算法,用于在主串中查找匹配子串的位置。
它的核心思想是通过利用已经匹配过的子串信息来避免不必要的匹配。
具体流程如下:
1. 预处理模式串
在KMP算法中,首先需要对模式串进行预处理,生成一个next 数组。
next数组中记录了模式串中每个字符前面最长的匹配前缀和后缀的长度。
2. 匹配主串
对于主串中的每个字符,逐个与模式串中的字符进行匹配。
如果匹配成功,则继续比较下一个字符;如果匹配失败,则根据next 数组跳转到模式串中下一个可能匹配的位置,继续匹配。
3. 返回匹配结果
如果成功匹配到了整个模式串,则返回匹配的起始位置;否则返回-1,表示匹配失败。
KMP算法的时间复杂度为O(m+n),其中m为模式串长度,n为主串长度。
该算法具有较好的性能和稳定性,在实际应用中得到了广泛的应用。
- 1 -。
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 <= S.length && j <= T.length){if (j == 0 || S.ch[i] == T.ch[j]){//数组第⼀位下标为1,0的意思为数组第⼀位的前⾯,此时++1,则指向数组的第⼀位元素++i;++j; //继续⽐较后继字符}elsej = next[j]; //模式串向右移动到第⼏个下标,序号(第⼀位从1开始)}if (j > 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 <= 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。
kmp算法python代码
kmp算法python代码摘要:1.KMP 算法简介2.KMP 算法的Python 实现3.KMP 算法的应用示例正文:1.KMP 算法简介KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,用于在一个主字符串中查找一个子字符串出现的位置。
该算法的关键在于通过预处理子字符串,减少不必要的字符比较,从而提高匹配速度。
2.KMP 算法的Python 实现以下是KMP 算法的Python 实现:```pythondef compute_prefix_function(pattern):m = len(pattern)prefix_function = [0] * (m + 1)prefix_function[0] = 0i, j = 1, 0while i < m:if pattern[i] == pattern[j]:j += 1prefix_function[i] = ji += 1else:if j!= 0:j = prefix_function[j - 1]else:prefix_function[i] = 0i += 1return prefix_functiondef kmp_search(text, pattern):m, n = len(text), len(pattern)prefix_function = compute_prefix_function(pattern) i, j = 0, 0while i < m:if pattern[j] == text[i]:i += 1j += 1if j == n:return i - jelif i < m and pattern[j]!= text[i]:if j!= 0:j = prefix_function[j - 1]else:i += 1return -1if __name__ == "__main__":text = "我国是一个伟大的国家"pattern = "伟大的"result = kmp_search(text, pattern)if result!= -1:print("子字符串"{}" 在主字符串中第{} 位置出现。
KMP算法(改进的模式匹配算法)——next函数
KMP算法(改进的模式匹配算法)——next函数KMP算法简介KMP算法是在基础的模式匹配算法的基础上进⾏改进得到的算法,改进之处在于:每当匹配过程中出现相⽐较的字符不相等时,不需要回退主串的字符位置指针,⽽是利⽤已经得到的部分匹配结果将模式串向右“滑动”尽可能远的距离,再继续进⾏⽐较。
在KMP算法中,依据模式串的next函数值实现字串的滑动,本随笔介绍next函数值如何求解。
next[ j ]求解将 j-1 对应的串与next[ j-1 ]对应的串进⾏⽐较,若相等,则next[ j ]=next[ j-1 ]+1;若不相等,则将 j-1 对应的串与next[ next[ j-1 ]]对应的串进⾏⽐较,⼀直重复直到相等,若都不相等则为其他情况题1在字符串的KMP模式匹配算法中,需先求解模式串的函数值,期定义如下式所⽰,j表⽰模式串中字符的序号(从1开始)。
若模式串p 为“abaac”,则其next函数值为()。
解:j=1,由式⼦得出next[1]=0;j=2,由式⼦可知1<k<2,不存在k,所以为其他情况即next[2]=1;j=3,j-1=2 对应的串为b,next[2]=1,对应的串为a,b≠a,那么将与next[next[2]]=0对应的串进⾏⽐较,0没有对应的串,所以为其他情况,也即next[3]=1;j=4,j-1=3 对应的串为a,next[3]=1,对应的串为a,a=a,所以next[4]=next[3]+1=2;j=5,j-1=4 对应的串为a,next[4]=2,对应的串为b,a≠b,那么将与next[next[4]]=1对应的串进⾏⽐较,1对应的串为a,a=a,所以next[5]=next[2]+1=2;综上,next函数值为 01122。
题2在字符串的KMP模式匹配算法中,需先求解模式串的函数值,期定义如下式所⽰,j表⽰模式串中字符的序号(从1开始)。
若模式串p为“tttfttt”,则其next函数值为()。
KMP算法详解
KMP算法详解KMP 算法详解KMP 算法是⼀个⼗分⾼效的字符串查找算法,⽬的是在⼀个字符串 s 中,查询 s 是否包含⼦字符串 p,若包含,则返回 p 在 s 中起点的下标。
KMP 算法全称为 Knuth-Morris-Pratt 算法,由 Knuth 和 Pratt 在1974年构思,同年 Morris 也独⽴地设计出该算法,最终由三⼈于1977年联合发表。
举⼀个简单的例⼦,在字符串 s = ababcabababca 中查找⼦字符串 p = abababca,如果暴⼒查找,我们会遍历 s 中的每⼀个字符,若 s[i] = p[0],则向后查询p.length() 位是否都相等。
这种朴素的暴⼒的算法复杂度为O(m×n),其中m和n分别是 p 和 s 的长度。
KMP 算法可以⽅便地简化这⼀查询的时间复杂度,达到O(m+n)。
1. PMT 序列PMT 序列是 KMP 算法的核⼼,即 Partial Match Table(部分匹配表)。
举个例⼦:char a b a b a b c aindex01234567PMT00123401PMT 的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。
PMT[0] = 0: 字符串 a 既没有前缀,也没有后缀;PMT[1] = 0: 字符串 ab 前缀集合为 {a},后缀集合为 {b},没有交集;PMT[2] = 1: 字符串 aba 前缀集合为 {a, ab},后缀集合为 {ba, a},交集为 {a},交集元素的最长长度为1;PMT[3] = 2: 字符串 abab 前缀集合为 {a, ab, aba},后缀集合为 {bab, ab, b},交集为 {ab},交集元素的最长长度为2;…… 以此类推。
2. 算法主体现在我们已经知道了 PMT 序列的含义,那么假设在 PMT 序列已经给定的情况下,如何加速字符串匹配算法?tar 存储 s 的下标,从 0 开始,若 tar > s.length() - 1,代表匹配失败;pos 存储 p 的下标,从 0 开始,若 s[tar] != p[pos],则 pos ⾛到下⼀个可能匹配的位置。
kmp算法next原理
kmp算法next原理
KMP算法,全称是Knuth-Morris-Pratt算法,是字符串匹配中一种高效率的算法。
该算法的核心是,利用已经匹配过的部分来减少比较次数。
具体实现是,当出现不匹配时,可以根据已经匹配的前缀和后缀的关系,避免重新匹配已经匹配过的字符,直接跳过这些字符,将模式串向后移动到下一个需要匹配的位置。
那么如何计算这个“已经匹配的前缀和后缀的关系”呢?这就需要用到next数组了。
next数组,本质上是一个数组,用于存储模式串的最长相同真前缀和真后缀的长度。
其中“真前缀”和“真后缀”,是指除了字符串本身的前缀和后缀,即不包含整个字符串的前缀和后缀。
通过预处理模式串生成next数组,我们就可以在匹配过程中根据已经匹配的前缀和后缀的长度,来跳过不必要的比较,从而达到优化匹配速度的目的。
以上就是KMP算法及其核心原理--next数组的简要介绍。
KMP
KMP算法
next函数的改进 函数的改进
aaabaaaab aaaa ① ② ③
j=4 j=3 j=2 j=1 i=4
j
12345
模式 a a a a b next[j] 0 1 2 3 4 nextval[j] 0 0 0 0 4
aaa aa a
aaaab i = 5; j = 1
next[j] = k,而pj=pk, , 主串中s 不等时, 则 主串中 i和pj不等时, 不需再和p 进行比较, 不需再和 k进行比较, 而直接和p 而直接和 next[k]进行比 较.
第 1 次匹配 s= cddcdc t=cdc 第 2 次匹配 s= cddcdc t=cdc 第 3 次匹配 s= cddcdc t=cdc 第 4 次匹配 s= cddcdc t=cdc i= 3 j= 3 i= 2 j= 1 i= 3 j= 1 i= 6 j= 3 成功 失败 失败 失败
i = i –j +2; j = 1;
KMP算法
j 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 模式串 a b c a a b b c a b c a a b d a b next[j] 0 1 1 1 2 2 3 1 1 2 3 4 5 6 7 1 2
nextval[j]
0 1 1 0 2 1 3 1 0 1 1 0 2 1 7 0 1
KMP算法
KMP算法的时间复杂度 KMP算法的时间复杂度 设主串s 的长度为n, 模式串t 长度为m, KMP算 n,模式串 m,在 设主串 s 的长度为 n, 模式串 t 长度为 m, 在 KMP 算 法中求next 数组的时间复杂度为 O(m),在后面的匹 法中求 next数组的时间复杂度为 O(m), 在后面的匹 next 数组的时间复杂度为O(m), 配中因主串s的下标不减即不回溯,比较次数可记为 配中因主串s的下标不减即不回溯, n,所以KMP算法总的时间复杂度为O(n+m). n,所以KMP算法总的时间复杂度为O(n+m). 所以KMP算法总的时间复杂度为O(n+m)
KMP算法-易懂版
KMP算法-易懂版⼀:定义 Knuth-Morris-Pratt 字符串查找算法,简称为 KMP算法,常⽤于快速查找⼀个母串S中是否包含⼦串(模式串)P,以及P出现的位置。
由于简单的暴⼒匹配中,每次遇到不匹配的位置时都要回溯到母串上⼀次的起点 i +1的位置上再次从⼦串的开头进⾏匹配,效率极其低下,故⽽KMP算法应运⽽⽣,减少回溯过程中不必要的匹配部分,加快查找速度。
⼆:kmp算法求解步骤描述 若当前不匹配的位置发⽣在母串位置 i,⼦串位置 j 上,则:1. 寻找⼦串位置 j 之前元素的最长且相等的前后缀,即最长公共前后缀。
记录这个长度。
2. 根据这个长度求 next 数组3. 若 j != 0, 则根据next [j] 中的值,将⼦串向右移动,也就是将公共前缀移到公共后缀的位置上,(代码表⽰为:j=next [j],注意 i 不变),即对位置 j 进⾏了更新,后续⼦串直接从更新后的 j 位置和母串 i 位置进⾏⽐较。
4. 若 j == 0,则 i+1,⼦串从j位置开始和母串 i+1 位置开始⽐较。
综上,KMP的next 数组相当于告诉我们:当⼦串中的某个字符跟母串中的某个字符匹配失败时,⼦串下⼀步应该跳到哪个位置开始和母串当前失配位置进⾏⽐较。
所以kmp算法可以简单解释为:如⼦串在j 处的字符跟母串在i 处的字符失配时,下⼀步就⽤⼦串next [j] 处的字符继续跟⽂本串 i 处的字符匹配,相当于⼦串⼀次向右移动 j - next[j] 位,跳过了⼤量不必要的匹配位置(OK,简单理解完毕之后,下⾯就是求解KMP的关键步骤,Let’s go! ) 三:kmp算法关键步骤之⼀,求最长的公共前后缀! 箭头表⽰当前匹配失败的位置,也就是当前的 j 位置。
⽩框表⽰最长公共前后缀AB!此时长度为2! 再来⼀个,此时最长公共前后缀为ABA!长度为3!四:kmp算法关键步骤之⼆,求next[ ] 数组 由步骤⼀,我们可以得到⼦串每个位置前⾯元素的最长共同前后缀,注意⼦串第⼀个位置是没有前后缀的,所以长度为0! 例:⼦串ABCDABD的最长公共前后缀可表⽰如下。
bf算法与kmp算法执行流程
bf算法与kmp算法执行流程英文回答:The Boyer-Moore (BM) algorithm and the Knuth-Morris-Pratt (KMP) algorithm are two popular string matching algorithms used to find occurrences of a pattern within a larger text. While both algorithms have the same goal, they differ in their approach and execution flow.The Boyer-Moore algorithm is a heuristic algorithm that uses two main techniques: the bad character rule and the good suffix rule. The bad character rule allows the algorithm to skip comparisons by shifting the pattern to align with the last occurrence of a mismatched character in the text. The good suffix rule, on the other hand, allows the algorithm to shift the pattern based on the longest suffix of the pattern that matches a prefix of itself.The execution flow of the Boyer-Moore algorithm can be summarized as follows:1. Preprocessing: The algorithm starts by preprocessing the pattern to create two lookup tables: the bad character table and the good suffix table.2. Searching: The algorithm then starts searching for the pattern in the text by aligning the pattern with the current position in the text and comparing characters from right to left.3. Mismatch: If a mismatch occurs, the algorithm uses the bad character rule to determine the amount of shift needed.4. Shift: The algorithm shifts the pattern to the right based on the maximum of the bad character rule and the good suffix rule.5. Repeat: Steps 3 and 4 are repeated until either a match is found or the end of the text is reached.The Knuth-Morris-Pratt algorithm, on the other hand, isa linear time algorithm that uses a failure function to avoid unnecessary comparisons. The failure function is computed based on the pattern itself and allows the algorithm to determine the maximum amount of shift when a mismatch occurs.The execution flow of the Knuth-Morris-Pratt algorithm can be summarized as follows:1. Preprocessing: The algorithm starts by preprocessing the pattern to create the failure function.2. Searching: The algorithm then starts searching for the pattern in the text by aligning the pattern with the current position in the text and comparing characters from left to right.3. Mismatch: If a mismatch occurs, the algorithm uses the failure function to determine the amount of shift needed.4. Shift: The algorithm shifts the pattern to the rightbased on the value of the failure function.5. Repeat: Steps 3 and 4 are repeated until either a match is found or the end of the text is reached.中文回答:Boyer-Moore(BM)算法和Knuth-Morris-Pratt(KMP)算法是两种常用的字符串匹配算法,用于在较大的文本中查找模式的出现。
kmp 最小循环节
kmp 最小循环节
【原创版】
目录
1.KMP 算法简介
2.最小循环节的概念
3.KMP 算法与最小循环节的关系
4.KMP 算法的应用实例
5.总结
正文
一、KMP 算法简介
KMP(Knuth-Morris-Pratt)算法是一种高效的字符串匹配算法,用
于在一个主字符串中查找一个子字符串出现的位置。
该算法的关键在于通过预处理子字符串,减少不必要的字符比较,从而提高匹配速度。
二、最小循环节的概念
最小循环节是指一个字符串中最短的、能够被重复用来匹配其他字符串的一段子串。
例如,字符串"ababc"的最小循环节是"abc"。
三、KMP 算法与最小循环节的关系
KMP 算法利用最小循环节的概念来提高字符串匹配的效率。
在预处理子字符串时,KMP 算法会尽量找到子字符串中的最小循环节,从而在匹配过程中,将匹配失败的部分尽可能地跳过,提高匹配速度。
四、KMP 算法的应用实例
假设我们需要在一个字符串"abcabcbb"中查找子字符串"abc"的位置。
使用 KMP 算法,我们可以先预处理子字符串"abc",找到其最小循环节为"abc",然后根据子字符串在主字符串中的出现位置,跳过不需要比较的
字符,最终得到匹配结果。
五、总结
KMP 算法通过利用最小循环节的概念,提高了字符串匹配的效率。
在实际应用中,KMP 算法具有较高的性能,被广泛应用于文本处理、信息检索等领域。
KMP算法
第一次匹配 a c a b a a b a a b c a c a a b c a b a a b c a c a c a b a a b a a b c a c a a b c a b a a b c a c
KMP算法 算法
第二次匹配
第三次匹配
a c a b a a b a a b c a c a a b c a b a a b c a c a c a b a a b a a b c a c a a b c a b a a b c a c
第四次匹配
可见,一旦s 比较不相等,主串s 可见,一旦si和tj比较不相等,主串s 的指针不一定要回朔,主串s 的指针不一定要回朔,主串si(或si+1)可 直接与t 0<=k〈 比较, 直接与tk(0<=k〈j)比较,k的决定与主串 并无关系,而只与模式串t s并无关系,而只与模式串t本身的构成有 即从模式串t本身就可求出k 关,即从模式串t本身就可求出k值。 讨论一般情况, s=“ 讨论一般情况,设s=“s0s1...sn-1”, t=“ 假定: t=“t0t1...tm-1”。假定:
且不可能存在某个k k满足上式 满足上式, 且不可能存在某个k’ > k满足上式,因此 next[j+1] = next[j]+1 = k+1;
此时可把求next[j+1] next[j+1]值的问 2、若tk<>tj,此时可把求next[j+1]值的问 题看作是一个模式匹配问题, 题看作是一个模式匹配问题,即把模式串 向右滑动至k =next[k](0<k’<k<j) t’向右滑动至k’=next[k](0<k’<k<j) 则说明在主串t中第j+1 j+1个字 ,若tk’=tj,则说明在主串t中第j+1个字 符之前存在一个长度为k 的子串满足: 符之前存在一个长度为k’的子串满足:
kmp算法next数组构造过程
kmp算法next数组构造过程
KMP算法的核心部分就是构造next数组,它的作用是在模式
串与目标串不匹配时,快速确定模式串需要移动的位置,从而避免不必要的比较操作。
下面是KMP算法中next数组的构造过程:
1. 首先,创建一个长度与模式串相同的数组next[],用于存储
每个位置的next值。
2. 将next[0]初始化为-1,next[1]初始化为0,这是因为当模式
串只有一个字符时,无法进行移动,所以next[1]为0。
3. 从位置2开始,使用一个指针i遍历整个模式串。
在遍历的
过程中,不断更新next[i]的值。
4. 对于每个位置的next[i],需要判断模式串中位置i之前的子
串的前缀与后缀是否存在重复。
具体操作如下:
- 首先,将next[i-1]的值赋给一个临时变量j,并递归比较j
与i-1位置的字符是否相等。
如果相等,则next[i]的值为j+1;如果不相等,则将next[j]的值再赋给j,重新进行比较。
- 重复上述过程,直到找到一个相等的前缀和后缀,或者不
能再递归比较为止。
5. 当指针i遍历完整个模式串后,next数组的构造过程完成。
这个构造过程的时间复杂度为O(m),其中m是模式串的长度。
通过构造好的next数组,可以快速确定模式串的移动位置,
从而提高匹配效率。
KMP算法的next函数求解和分析过程
KMP算法的next函数求解和分析过程转⾃:/wang0606120221/article/details/7402688假设KMP算法中的模式串为P,主串为S,那么该算法中的核⼼是计算出模式串的P的next函数。
KMP算法是在已知的模式串的next函数值的基础上进⾏匹配的。
由于本次只讨论next的求值过程,因此KMP算法的数学推理过程这⾥不再讲解。
从KMP算法的数学推理可知,此next函数只取决与模式匹配串⾃⾝的特点和主串没有任何关系,此函数默认认为next[1]=0,由于next[j]=k表⽰的意义是当模式串和主串的第j个字符不匹配时,那么接下来和主串的第j个字符匹配的字符是模式串的第k个字符。
因此,next[1]=0表⽰当主串的当前字符和模式串的第1个字符不匹配,接下来需要⽤模式串的第0个字符和主串的当前字符匹配,由于模式串下标是从1开始的,所以不可能存在第0个字符,即接下的匹配动作是主串和模式串同时向右移动⼀位,继续模式匹配。
例如:主串:a c a b a a b a a b n a c模式串:a b a a b主串:a c a b a a b a a b n a c模式串: a b a a b主串:a c a b a a b a a b n a c模式串: a b a a b此时,主串和模式串不匹配,⽽next[1]=0,因此,模式串的第0个字符和主串的第2个字符⽐较,⽽模式串没有第0个字符,此时可以把第0个字符理解为空字符,即模式串向右移动⼀位,主串再继续喝模式串匹配,⽽此时的主串的当前字符是第3个字符,整体来看是当主串和模式串的第1个字符不匹配时,主串和模式串同时右移⼀位,然后继续匹配。
接下来讲解⼀般情况下的next函数值求解过程。
设next[j]=k,根据KMP算法的模式串的特点可知,‘p1p2......pk-1’=‘pj-k+1......pj-1’,其中k必须满⾜1<k<j,并且不可能存在k‘>k满⾜上⾯等式。
kmp百度百科
kmp算法[编辑本段]kmp算法-概述一种改进的字符串匹配算法,由 D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。
[编辑本段]kmp算法-学习介绍完全掌握KMP算法思想学过数据结构的人,都对KMP算法印象颇深。
尤其是新手,更是难以理解其涵义,搞得一头雾水。
今天我们就来面对它,不将它彻底搞懂,誓不罢休。
如今,大伙基本上都用严蔚敏老师的书,那我就以此来讲解KMP 算法。
(小弟正在备战考研,为了节省时间,很多课本上的话我都在此省略了,以后一定补上。
)严老的《数据结构》79页讲了基本的匹配方法,这是基础。
先把这个搞懂了。
80页在讲KMP算法的开始先举了个例子,让我们对KMP的基本思想有了最初的认识。
目的在于指出“由此,在整个匹配的过程中,i指针没有回溯,”。
我们继续往下看:现在讨论一般情况。
假设主串:s: ‘s(1) s(2) s(3) ……s(n)’; 模式串:p: ‘p(1) p(2) p(3)…..p(m)’把课本上的这一段看完后,继续现在我们假设主串第i个字符与模式串的第j(j<=m)个字符‘失配’后,主串第i个字符与模式串的第k(k<j)个字符继续比较此时,s(i)≠p(j), 有主串:S(1)……s(i-j+1)……s(i-1) s(i) ………….|| (相配) || ≠(失配)匹配串:P(1) ……. p(j-1) p(j)由此,我们得到关系式‘p(1) p(2) p(3)…..p(j-1)’= ’s(i-j+1)……s(i-1)’由于s(i)≠p(j),接下来s(i)将与p(k)继续比较,则模式串中的前(k-1)个字符的子串必须满足下列关系式,并且不可能存在k’>k 满足下列关系式:(k<j),‘p(1) p(2) p(3)…..p(k-1)’= ’s(i-k+1)s(i-k+2)……s(i-1)’即:主串:S(1)……s(i-k +1) s(i-k +2) ……s(i-1) s(i) ………….|| (相配) || || ?(有待比较)匹配串:P(1) p(2) ……p(k-1) p(k)现在我们把前面总结的关系综合一下有:S(1)…s(i-j +1)…s(i-k +1) s(i-k +2) ……s(i-1) s(i) ……|| (相配) || || || ≠(失配)P(1) ……p(j-k+1) p(j-k+2) ….... p(j-1) p(j)|| (相配) || || ?(有待比较)P(1) p(2) ……. p(k-1) p(k)由上,我们得到关系:‘p(1) p(2) p(3)…..p(k-1)’= ’s(j-k+1)s(j-k+2)……s(j-1)’接下来看“反之,若模式串中存在满足式(4-4)。
kmp算法的next数组
kmp算法的next数组KMP算法的Next数组KMP算法是一种字符串匹配算法,它的核心思想是利用已知信息来避免无效的比较。
在KMP算法中,Next数组是一个非常重要的概念,它可以帮助我们快速地匹配字符串。
Next数组的定义Next数组是一个长度为模式串长度的数组,它的每个元素表示在模式串中,从当前位置开始往后匹配的最长公共前后缀的长度。
例如,对于模式串“ABCDABD”,它的Next数组为[0,0,0,0,1,2,0]。
其中,Next[0]=0,因为从第一个字符开始往后匹配,没有任何公共前后缀;Next[4]=1,因为从第五个字符开始往后匹配,最长的公共前后缀为“A”;Next[5]=2,因为从第六个字符开始往后匹配,最长的公共前后缀为“AB”。
Next数组的求解求解Next数组的过程可以分为两个步骤:预处理和匹配。
预处理:对于模式串中的每个位置i,求出从i开始往后匹配的最长公共前后缀的长度。
具体地,我们可以从模式串的第二个字符开始,依次计算每个位置的Next值。
假设当前位置为i,已知Next[0]~Next[i-1]的值,我们需要求出Next[i]的值。
具体地,我们可以分为两种情况:1. 如果模式串中i位置的字符与前面的某个位置j的字符相同,那么Next[i]=Next[j]+1。
这是因为如果从i开始往后匹配失败,那么我们可以将模式串向右移动j-Next[j]个位置,这样就可以避免重复比较前面已经匹配过的部分。
2. 如果模式串中i位置的字符与前面的某个位置j的字符不同,那么我们需要继续往前找,直到找到一个位置k,使得模式串中从k 开始往后的子串与从i开始往后的子串相同。
此时,Next[i]=Next[k]+1。
匹配:在匹配过程中,我们需要利用Next数组来避免无效的比较。
具体地,假设我们已经匹配了文本串中的前i个字符和模式串中的前j个字符,此时发现模式串中的第j+1个字符与文本串中的第i+1个字符不匹配。
K M P 算 法 详 解
KMP算法详解(转)此前一天,一位MS的朋友邀我一起去与他讨论快速排序,红黑树,字典树,B树、后缀树,包括KMP算法,唯独在讲解KMP算法的时候,言语磕磕碰碰,我想,原因有二:1、博客内的东西不常回顾,忘了不少;2、便是我对KMP算法的理解还不够彻底,自不用说讲解自如,运用自如了。
所以,特再写本篇文章。
由于此前,个人已经写过关于KMP算法的两篇文章,所以,本文名为:KMP算法之总结篇。
本文分为如下六个部分:第一部分、再次回顾普通的BF算法与KMP算法各自的时间复杂度,并两相对照各自的匹配原理;第二部分、通过我此前第二篇文章的引用,用图从头到尾详细阐述KMP算法中的next数组求法,并运用求得的next数组写出KMP算法的源码;第三部分、KMP算法的两种实现,代码实现一是根据本人关于KMP算法的第二篇文章所写,代码实现二是根据本人的关于KMP算法的第一篇文章所写;第四部分、测试,分别对第三部分的两种实现中next数组的求法进行测试,挖掘其区别之所在;第五部分、KMP完整准确源码,给出KMP算法的准确的完整源码;第六步份、一眼看出字符串的next数组各值,通过几个例子,让读者能根据字符串本身一眼判断出其next数组各值。
力求让此文彻底让读者洞穿此KMP算法,所有原理,来龙去脉,让读者搞个通通透透(注意,本文中第二部分及第三部分的代码实现一的字符串下标i从0开始计算,其它部分如第三部分的代码实现二,第五部分,和第六部分的字符串下标i 皆是从1开始的)。
第一部分、KMP算法初解1、普通字符串匹配BF算法与KMP算法的时间复杂度比较KMP算法是一种线性时间复杂的字符串匹配算法,它是对BF算法(Brute-Force,最基本的字符串匹配算法的)改进。
对于给的原始串S 和模式串P,需要从字符串S中找到字符串P出现的位置的索引。
BF算法的时间复杂度O(strlen(S) * strlen(T)),空间复杂度O(1)。
KMP算法(推导方法及模板)
KMP算法(推导⽅法及模板)介绍克努斯-莫⾥斯-普拉特算法Knuth-Morris-Pratt(简称为KMP算法)可在⼀个主⽂本S内查找⼀个词W的出现位置。
此算法通过运⽤对这个词在不匹配时本⾝就包含⾜够的信息来确定下⼀个匹配将在哪⾥开始的发现,从⽽避免重新检查先前匹配的。
此算法可以在O(n+m)时间数量级上完成串的模式匹配操作,其改进在于:每当⼀趟匹配过程中出现字符⽐较不等时,不需回溯i的指针,⽽是利⽤已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离后,继续进⾏⽐较。
kmp的核⼼之处在于next数组,⽽为了⽅便理解,我先介绍KMP的思想KMP匹配当开始匹配时,如果匹配过程中产⽣“失配”时,指针i(原串的下标)不变,指针j(模式串的下标)退回到next[j] 所指⽰的位置上重新进⾏⽐较,并且当指针j退回⾄零时,指针i和指针j需同时加⼀。
即主串的第i个字符和模式的第⼀个字符不等时,应从主串的第i+1个字符起重新进⾏匹配。
简单来说,就是两个串匹配,如果当前字符相等就⽐较两个字符串的下⼀个字符,如果当前匹配不相等时,就让j(待匹配串的下标)回到next[j] 的位置,因为我们已经知道next数组的作⽤是利⽤已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的距离,如ababac与abac⽐较时i=4,j=4时不匹配,则利⽤next数组让j=2继续匹配⽽不⽤重新开始。
(⽬前先不⽤管next数组的值时如何得到的,只要明⽩它的作⽤即可,下⾯回介绍)所以我们可以写出kmp的代码int KMP(char str[],char pat[]){int lenstr=strlen(str);int lenpat=strlen(pat);int i=1,j=1;while(i<=lenstr){if(j==0 || str[i]==pat[j]) //匹配成功继续往后匹配++i,++j;elsej=next[j]; //否则根据next数组继续匹配if(j==lenpat) //说明匹配完成return 1;}return 0;}接下来就是关键的求next数组了next数组⾸先,next数组取决于模式串本⾝⽽与相匹配的主串⽆关,我们可以对其递推得到。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
kmp算法流程
KMP算法流程:
1.定义两个指针i和j,分别指向模式串和匹配串的初始位置,初始化i=0,j=0。
2. 预处理获取模式串的next数组。
3.如果模式串的第i个字符等于匹配串的第j个字符,将i和j分别向后移动一位,即i=i+1,j=j+1。
4. 如果模式串的第i个字符不等于匹配串的第j个字符,则将i更新为next[i],即将i跳到next[i]的位置,j不动。
5.重复步骤3和步骤4,直到匹配成功(即j匹配成功)或者匹配失败(j超过了匹配串的长度)。
KMP算法的核心思想是利用模式串的信息来避免无效匹配。
next数组是KMP算法的关键,它记录了模式串中每个位置的最长相等前缀和后缀的长度。
在匹配过程中,如果当前匹配到模式串的某个位置i和匹配串的某个位置j不匹配,那么就可以根据next数组跳过一些无需匹配的位置,从而能够提高匹配效率。