详解KMP算法中Next数组的求法

合集下载

计算模式串t的next数组和nextval数组的值

计算模式串t的next数组和nextval数组的值

计算模式串t的next数组和nextval数组的值在字符串匹配问题中,常常会用到模式串的next数组和nextval数组,这两个数组用于加速字符串的匹配过程。

1. next数组的计算:next[i]的值表示模式串t中,以第i个字符结尾的前缀字符串与后缀字符串的最长公共部分的长度。

具体计算方法如下:(1)首先求出模式串t的长度,假设为m;(2)初始化next数组的第一个元素next[0]为-1;(3)遍历模式串t的每个字符,假设当前遍历的字符是t[i]:- 初始化j = next[i - 1],j表示最大的相同前后缀的长度;- 如果t[j] == t[i],说明下一个最长的相同前后缀长度可以加1,即next[i] = j + 1;-如果t[j]!=t[i],则需要不断向前回溯,直到找到一个长度更小的相同前后缀,或者回溯到开始位置;-重复上述过程,直到遍历完整个模式串。

2. nextval数组的计算:相对于next数组来说,nextval数组的计算过程更为复杂,但是在一些情况下,它的效率更高。

具体计算方法如下:(1)首先求出模式串t的长度,假设为m;(2)初始化nextval数组的第一个元素nextval[0]为-1;(3)遍历模式串t的每个字符,假设当前遍历的字符是t[i]:- 初始化j = nextval[i - 1],j表示最大的相同前后缀的长度;- 如果t[j] == t[i],说明下一个最长的相同前后缀长度可以加1,即nextval[i] = j + 1;-如果t[j]!=t[i],则需要继续向前回溯,寻找到一个长度更小的相同前后缀;-如果t[j]!=t[i],则需要继续向前回溯,寻找到一个长度更小的相同前后缀;-如果j=-1,说明已经回溯到模式串的开始位置;-如果t[j]==t[i],说明找到了一个长度更小的相同前后缀;- 根据上述步骤的结果,得到nextval[i]的值。

需要注意的是,计算next数组和nextval数组的过程都是从模式串的第二个字符开始的,所以需要先初始化数组的第一个元素为-1下面以一个例子来具体说明如何计算next数组和nextval数组:假设模式串t为"ABCDABD",则模式串的长度为7首先计算next数组:- t[0]前面没有字符,所以next[0] = -1;- 遍历到t[1] = 'B',此时j = next[0] = -1;- t[j] = t[-1],跳过此步骤,直接执行next[1] = 0;- 遍历到t[2] = 'C',此时j = next[1] = 0;-t[j]!=t[2],需要继续向前回溯,因为j=0;- t[j] = t[-1],跳过此步骤,直接执行next[2] = 0;- 遍历到t[3] = 'D',此时j = next[2] = 0;-t[j]!=t[3],需要继续向前回溯,因为j=0;- t[j] = t[-1],跳过此步骤,直接执行next[3] = 0;- 遍历到t[4] = 'A',此时j = next[3] = 0;-t[j]!=t[4],需要继续向前回溯,因为j=0;- t[j] = t[-1],跳过此步骤,直接执行next[4] = 0;- 遍历到t[5] = 'B',此时j = next[4] = 0;-t[j]!=t[5],需要继续向前回溯,因为j=0;- t[j] = t[-1],跳过此步骤,直接执行next[5] = 0;- 遍历到t[6] = 'D',此时j = next[5] = 0;-t[j]!=t[6],需要继续向前回溯,因为j=0;- t[j] = t[-1],跳过此步骤,直接执行next[6] = 0;所以模式串t的next数组为:[-1, 0, 0, 0, 0, 0, 0]。

KMP算法Next数组详解

KMP算法Next数组详解

KMP算法Next数组详解题⾯题⽬描述如题,给出两个字符串s1和s2,其中s2为s1的⼦串,求出s2在s1中所有出现的位置。

为了减少骗分的情况,接下来还要输出⼦串的前缀数组next。

如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习⼀下就知道了。

输⼊输出格式输⼊格式:第⼀⾏为⼀个字符串,即为s1(仅包含⼤写字母)第⼆⾏为⼀个字符串,即为s2(仅包含⼤写字母)输出格式:若⼲⾏,每⾏包含⼀个整数,表⽰s2在s1中出现的位置接下来1⾏,包括length(s2)个整数,表⽰前缀数组next[i]的值。

输⼊样例:ABABABCABA输出样例:130 0 1说明时空限制:1000ms,128M数据规模:设s1长度为N,s2长度为M对于30%的数据:N<=15,M<=5对于70%的数据:N<=10000,M<=100对于100%的数据:N<=1000000,M<=1000题解这是⼀道KMP裸题(模板题。

)我就是拿着它学习⼀下KMP算法其实原来我学过KMP算法但是⼀直没有弄懂next(跳转)数组是如何求出来的。

最近花了⼀个下午⾃⼰研究了⼀下KMP算法现在终于觉得KMP很简单了~现在直接说next数组把⾄于有什么作⽤,next数组是⼲什么的,请⾃⾏百度,有很多dalao总结的⾮常到位,看⼀看就会明⽩。

好,来说next数组并不⽤在意这⼀坨⿊的是什么东西,我们就假设他是我们要求next数组的字符串。

next数组求的东西就是从起始位置到当前位置最长的相等的前缀和后缀的长度。

(举个例⼦China的前缀有:C、Ch、Chi、Chin、China ;后缀有a、na、ina、hina、China)我们继续,如上图红⾊的是当前位置(设为j)前,所匹配上的最长前缀和后缀,蓝⾊的是当前要匹配的位置。

那么,我们就拿当前位置和原来匹配到的最长前缀的后⼀位相⽐较如果两个位置相同,显然,可以和前⾯的红⾊连在⼀起,此时就有next[j]=next[j-1]+1如果两个位置不相同,根据next数组的性质,显然的,你的当前的相等的前缀和后缀只能够继续向前找,也就是说,你当前的next数组⼀定会减⼩。

kmp算法流程

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数组)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。

kmp算法next计算方法

kmp算法next计算方法

kmp算法next计算方法KMP算法是一种字符串匹配算法,它的核心在于利用已经部分匹配的信息来减少匹配的次数,从而提高匹配的效率。

而KMP算法中的next数组计算方法则是KMP算法的关键之一,它是用来存储模式串中前缀和后缀的最长公共元素的长度。

接下来我们将详细介绍KMP算法中next数组的计算方法。

首先,我们需要了解next数组的含义。

next数组是针对模式串而言的,它的长度与模式串的长度相同。

next数组中的每个元素表示在当前位置之前的字符串中,有多大长度的相同前缀和后缀。

例如,对于模式串"ababaca",其next数组为[-1, 0, 0, 1, 2, 3, 0],表示在每个位置之前的字符串中,有多大长度的相同前缀和后缀。

接下来,我们来介绍如何计算next数组。

假设模式串的长度为m,我们需要计算出next[1]到next[m-1]的值。

首先,我们可以将next[0]的值设为-1,这是因为next数组中的值表示的是前缀和后缀的最长公共元素的长度,而在第一个位置之前并没有字符串,因此其值为-1。

接着,我们从第二个位置开始计算next数组的值。

假设我们已经知道next[i-1]的值,现在我们来计算next[i]的值。

如果模式串的第i个字符和第next[i-1]+1个字符相等,那么next[i]的值就是next[i-1]+1;如果不相等,我们就需要继续往前找前缀和后缀的最长公共元素的长度,直到找到相等的情况或者完全没有相等的情况。

具体的计算方法可以用如下的伪代码表示:```python。

def getNextArray(s):n = len(s)。

next = [-1] n。

k = -1。

j = 0。

while j < n 1:if k == -1 or s[j] == s[k]:k += 1。

j += 1。

next[j] = k。

else:k = next[k]return next。

kmp算法next函数详解

kmp算法next函数详解

kmp算法next函数详解KMP算法在介绍KMP算法之前,先介绍⼀下BF算法。

⼀.BF算法BF算法是普通的模式匹配算法,BF算法的思想就是将⽬标串S的第⼀个字符与模式串P的第⼀个字符进⾏匹配,若相等,则继续⽐较S的第⼆个字符和P的第⼆个字符;若不相等,则⽐较S的第⼆个字符和P的第⼀个字符,依次⽐较下去,直到得出最后的匹配结果。

举例说明:S: ababcababaP: ababaBF算法匹配的步骤如下i=0 i=1 i=2 i=3 i=4第⼀趟:a babcababa 第⼆趟:a b abcababa 第三趟:ab a bcababa 第四趟:aba b cababa 第五趟:abab c ababaa baba ab aba ab a ba aba b a abab aj=0 j=1 j=2 j=3 j=4(i和j回溯)i=1 i=2 i=3 i=4 i=3第六趟:a b abcababa 第七趟:ab a bcababa 第⼋趟:aba b cababa 第九趟:abab c ababa 第⼗趟:aba b cababaa baba a baba ab aba ab a ba a babaj=0 j=0 j=1 j=2(i和j回溯) j=0i=4 i=5 i=6 i=7 i=8第⼗⼀趟:abab c ababa 第⼗⼆趟:ababc a baba 第⼗三趟:ababca b aba 第⼗四趟:ababcab a ba 第⼗五趟:ababcaba b aa baba a baba ab aba ab a ba aba b aj=0 j=0 j=1 j=2 j=3i=9第⼗六趟:ababcabab aabab aj=4(匹配成功)代码实现:int BFMatch(char*s,char*p){int i,j;i=0;while(i<strlen(s)){j=0;while(s[i]==p[j]&&j<strlen(p)){i++;j++;}if(j==strlen(p))return i-strlen(p);i=i-j+1; //指针i回溯}return-1;}其实在上⾯的匹配过程中,有很多⽐较是多余的。

kmp算法中模式字符串的nextval数组

kmp算法中模式字符串的nextval数组

在KMP 算法中,模式字符串的next 数组是一个关键部分。

next 数组的作用是存储模式字符串中每个字符的最长相等前缀后缀的长度。

这个数组有助于在匹配过程中跳过尽可能多的字符,从而提高匹配效率。

next 数组的计算方法如下:1. 初始化next 数组为长度为1 的数组,存储第一个字符的长度。

2. 遍历模式字符串的每个字符,对于每个字符,计算其最长前缀后缀的长度。

3. 更新next 数组,将当前字符的最长前缀后缀长度加1,并存储在next 数组中。

以下是一个简单的KMP 算法实现,其中包含next 数组的计算:```pythondef kmp_preprocess(pattern):next = [1] * len(pattern)j = 0for i in range(1, len(pattern)):while j > 0 and pattern[i] != pattern[j]:j = next[j - 1]if pattern[i] == pattern[j]:j += 1next[i] = jreturn nextdef kmp_search(text, pattern):next = kmp_preprocess(pattern)i = 0j = 0while i < len(text):while j > 0 and text[i] != pattern[j]:i += 1if text[i] == pattern[j]:i += 1j += 1if j == len(pattern):return i - jreturn -1text = "我国是一个伟大的国家"pattern = "国家"result = kmp_search(text, pattern)print(result)```在这个例子中,我们首先计算next 数组,然后使用next 数组进行文本匹配。

abaabaab的next数组

abaabaab的next数组

abaabaab的next数组是指在字符串abaabaab中,每个前缀的最长相等真前后缀的长度数组。

这个数组在字符串匹配算法中非常重要,它可以帮助我们更快地进行字符串匹配,提高算法的效率。

为了更好地理解abaabaab的next数组,我们首先需要了解字符串匹配算法中的KMP算法。

KMP算法是一种经典的字符串匹配算法,它利用了字符串本身的信息,在匹配过程中尽量减少回溯,以达到提高匹配效率的目的。

在KMP算法中,我们需要先构建出模式串的next数组。

这个next数组其实是一个关于模式串的自身匹配情况的数组,它的定义如下:1. 对于模式串P中的每一个位置i,next[i]的值代表P[0]到P[i]这个子串的最长相等真前后缀的长度。

2. 如果模式串P的长度为n,则next数组的长度也为n。

以abaabaab为例,它的next数组为[0, 0, 1, 1, 2, 3, 4, 5]。

下面我们来详细解释一下这个数组是如何得出的。

1. 我们先来求出每个位置的最长相等真前后缀的长度。

位置0:a,这个位置是一个单字符,自身没有真前后缀,所以长度为0。

位置1:ab,这个位置没有真前后缀,长度为0。

位置2:aba,这个位置的最长相等真前后缀为a,长度为1。

位置3:abaa,这个位置的最长相等真前后缀为a,长度为1。

位置4:abaab,这个位置的最长相等真前后缀为aba,长度为3。

位置5:abaaba,这个位置的最长相等真前后缀为abaab,长度为4。

位置6:abaabaa,这个位置的最长相等真前后缀为abaaba,长度为5。

位置7:abaabaab,这个位置的最长相等真前后缀为abaabaa,长度为5。

经过上面的计算,我们得到了abaabaab的next数组为[0, 0, 1, 1, 2, 3, 4, 5]。

2. 接下来我们来讨论一下如何利用这个next数组来进行字符串匹配。

假设我们现在有一个文本串T和一个模式串P,我们希望在文本串T中找到模式串P的位置。

数据结构教学中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中的一个连续的字符序列相等,则称匹配成功,否则称匹配不成功。

详解KMP算法中Next数组的求法

详解KMP算法中Next数组的求法

详解KMP算法中Next数组的求法例如:1 2 3 4 5 6 7 8模式串 a b a a b c a cnext值0 1 1 2 2 3 1 2next数组的求解方法是:第一位的next值为0,第二位的next 值为1,后面求解每一位的next值时,根据前一位进行比较。

首先将前一位与其next值对应的内容进行比较,如果相等,则该位的next 值就是前一位的next值加上1;如果不等,向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值;如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1。

看起来很令人费解,利用上面的例子具体运算一遍。

1.前两位必定为0和1。

2.计算第三位的时候,看第二位b的next值,为1,则把b和1对应的a进行比较,不同,则第三位a的next的值为1,因为一直比到最前一位,都没有发生比较相同的现象。

3.计算第四位的时候,看第三位a的next值,为1,则把a和1对应的a进行比较,相同,则第四位a的next的值为第三位a的next 值加上1。

为2。

因为是在第三位实现了其next值对应的值与第三位的值相同。

4.计算第五位的时候,看第四位a的next值,为2,则把a和2对应的b进行比较,不同,则再将b对应的next值1对应的a与第四位的a进行比较,相同,则第五位的next值为第二位b的next值加上1,为2。

因为是在第二位实现了其next值对应的值与第四位的值相同。

5.计算第六位的时候,看第五位b的next值,为2,则把b和2对应的b进行比较,相同,则第六位c的next值为第五位b的next 值加上1,为3,因为是在第五位实现了其next值对应的值与第五位相同。

6.计算第七位的时候,看第六位c的next值,为3,则把c和3对应的a进行比较,不同,则再把第3位a的next值1对应的a与第六位c比较,仍然不同,则第七位的next值为1。

KMP算法中next数组的理解与算法的实现(java语言)

KMP算法中next数组的理解与算法的实现(java语言)

KMP算法中next数组的理解与算法的实现(java语⾔)KMP 算法我们有写好的函数帮我们计算 Next 数组的值和 Nextval 数组的值,但是如果是考试,那就只能⾃⼰来⼿算这两个数组了,这⾥分享⼀下我的计算⽅法吧。

计算前缀 Next[i] 的值:我们令 next[0] = -1 。

从 next[1] 开始,每求⼀个字符的 next 值,就看它前⾯是否有⼀个最长的"字符串"和从第⼀个字符开始的"字符串"相等(需要注意的是,这2个"字符串"不能是同⼀个"字符串")。

如果⼀个都没有,这个字符的 next 值就是0;如果有,就看它有多长,这个字符的next 值就是它的长度。

计算修正后的 Nextval[i] 值:我们令 nextval[0] = -1。

从 nextval[1] 开始,如果某位(字符)与它 next 值指向的位(字符)相同,则该位的 nextval 值就是指向位的 nextval 值(nextval[i] = nextval[ next[i] ]);如果不同,则该位的 nextval 值就是它⾃⼰的 next 值(nextvalue[i] = next[i])。

举个例⼦:计算前缀 Next[i] 的值:next[0] = -1;定值。

next[1] = 0;s[1]前⾯没有重复⼦串。

next[2] = 0;s[2]前⾯没有重复⼦串。

next[3] = 0;s[3]前⾯没有重复⼦串。

next[4] = 1;s[4]前⾯有重复⼦串s[0] = 'a'和s[3] = 'a'。

next[5] = 2;s[5]前⾯有重复⼦串s[01] = 'ab'和s[34] = 'ab'。

next[6] = 3;s[6]前⾯有重复⼦串s[012] = 'abc'和s[345] = 'abc'。

kmp next算法

kmp next算法

kmp next算法KMP算法(Knuth-Morris-Pratt Algorithm)是一种字符串匹配算法,它的核心思想是利用已经得到的匹配结果,尽量减少字符的比较次数,提高匹配效率。

本文将详细介绍KMP算法的原理、实现方法以及应用场景。

一、KMP算法的原理KMP算法的核心是构建next数组,用于指导匹配过程中的回溯操作。

next数组的定义是:对于模式串中的每个字符,记录它前面的子串中相同前缀和后缀的最大长度。

next数组的长度等于模式串的长度。

具体来说,KMP算法的匹配过程如下:1. 初始化主串指针i和模式串指针j为0。

2. 逐个比较主串和模式串对应位置的字符:- 若主串和模式串的字符相等,i和j同时后移一位。

- 若主串和模式串的字符不相等,根据next数组的值,将模式串指针j回溯到合适的位置,继续匹配。

二、KMP算法的实现KMP算法的实现可以分为两个步骤:构建next数组和利用next数组进行匹配。

1. 构建next数组:- 首先,next[0]赋值为-1,next[1]赋值为0。

- 然后,从第2个位置开始依次计算next[i],根据前一个位置的next值和模式串的字符进行判断:- 若前一个位置的next值为-1或模式串的字符与前一个位置的字符相等,则next[i] = next[i-1] + 1。

- 若前一个位置的next值不为-1且模式串的字符与前一个位置的字符不相等,则通过next数组的回溯操作,将模式串指针j回溯到合适的位置,继续判断。

2. 利用next数组进行匹配:- 在匹配过程中,主串指针i和模式串指针j会同时后移:- 若主串和模式串的字符相等,i和j同时后移一位。

- 若主串和模式串的字符不相等,则根据next数组的值,将模式串指针j回溯到合适的位置,继续匹配。

三、KMP算法的应用场景KMP算法在字符串匹配中有广泛的应用,特别是在大规模文本中的模式匹配问题上具有明显的优势。

以下是KMP算法的几个应用场景:1. 子串匹配:判断一个字符串是否是另一个字符串的子串。

KMP算法的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算法中的next数组实例解释

kmp算法中的next数组实例解释

kmp算法中的next数组实例解释假设求串′ababaaababaa′的next数组模式串a b a b a a a b a b a a下标1234567891011121、前两位:next数组前两位⼀定是0,1 即前两位ab对应的next数组为01,则:模式串a b a b a a a b a b a a下标123456789101112next数组012、接下来看第三位,按照next数组求解⽅法。

第三位a的前⼀位为第⼆位的b,b的next值为1对应内容为a,b与a不同,向前继续寻找next值对应的内容来与前⼀位进⾏⽐较。

因为找到第⼀位都没有找到与前⼀位相等的内容,所以第三位a的next值为1,则:模式串a b a b a a a b a b a a下标123456789101112next数组0113、接下来看第四位b,b的前⼀位a的next值1对应内容为a,相同,所以该位b的next值就是前⼀位a的next值加上1,即为2模式串a b a b a a a b a b a a下标123456789101112next数组01124、接下来看第五位a,a的前⼀位b的next值2对应内容为b,相等,所以该位a的next值就是前⼀位b的next值加上1,即为3模式串a b a b a a a b a b a a下标123456789101112next数组011235、接下来看第六位a,a的前⼀位a的next值3对应内容为a,相等,所以该位a的next值就是前⼀位a的next值加上1,即为4模式串a b a b a a a b a b a a下标123456789101112next数组0112346、接下来看第七位a,a的前⼀位a的next值4对应内容为b,不相等,向前继续寻找next值对应的内容来与前⼀位进⾏⽐较,b的next值2对应的内容为b,依旧不相等,继续向前寻找,第⼆位b的next值1对应内容为a,相等。

kmp算法的next数组

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 算 法 详 解

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算法next计算方法

kmp算法next计算方法

kmp算法next计算方法KMP算法是一种字符串匹配的经典算法,它的核心在于利用已经部分匹配的信息来减少匹配的次数,从而提高匹配的效率。

而在KMP算法中,next数组的计算是至关重要的一步,它可以帮助我们快速定位到模式串中与文本串不匹配的位置,从而避免不必要的匹配操作。

本文将详细介绍KMP算法中next数组的计算方法。

首先,我们需要了解next数组的含义。

在KMP算法中,next数组用于记录模式串中每个位置的最长公共前缀和最长公共后缀的长度。

具体来说,对于模式串P,其next数组的第i个位置的值next[i]表示P[0]到P[i]这个子串的最长公共前缀和最长公共后缀的长度。

这样,当P[i]与T[j]不匹配时,我们就可以利用next数组中的信息来将模式串P相对于文本串T右移若干位,从而减少匹配的次数。

接下来,我们来介绍next数组的计算方法。

假设模式串P的长度为m,则next数组的长度也为m。

我们首先将next[0]赋值为-1,next[1]赋值为0,这是因为长度为1的子串没有真正的前缀和后缀。

然后,我们使用两个指针i和j来遍历模式串P,其中i从2开始,j从0开始。

在计算next[i]的过程中,我们需要考虑P[i-1]和P[j]两个字符。

如果P[i-1]等于P[j],则说明P[0]到P[i-1]这个子串的最长公共前缀和最长公共后缀的长度是j+1,于是我们将next[i]赋值为j+1,然后将i和j分别加1。

如果P[i-1]不等于P[j],则我们需要将j更新为next[j],然后继续比较P[i-1]和P[j]两个字符,直到找到相等的字符或者j变为0为止。

重复以上步骤,直到计算出整个next数组为止。

这样,我们就得到了模式串P的next数组。

通过计算得到的next数组,我们可以在KMP算法中利用部分匹配的信息来快速移动模式串,从而提高匹配的效率。

因此,next数组的计算是KMP算法中非常重要的一步,它直接影响到算法的性能和效率。

kmp算法中模式串的next数组值

kmp算法中模式串的next数组值

kmp算法中模式串的next数组值
模式串的next数组值是一个与模式串长度相同的数组,用于
指示当匹配失败时应该回退的位置。

计算next数组的方法如下:
1. 首先将next[0]赋值为-1,表示第一个位置没有可回退的位置。

2. 然后,从第二个位置开始,依次计算next[i]的值。

3. 假设已经计算出next[i-1]的值,即前i-1个字符的最长公共
前后缀的长度为next[i-1]。

4. 如果模式串的第i个字符与前i-1个字符的最长公共前后缀
的下一个字符相等,则next[i] = next[i-1] + 1。

5. 如果模式串的第i个字符与前i-1个字符的最长公共前后缀
的下一个字符不相等,则需要不断回退,直到找到一个位置j,使得模式串的前j个字符与前i-1个字符的前j个字符相等。

6. 因此,需要将next[i-1]的值作为起点,依次向左比较,找到
这个位置j。

7. 如果找到了这个位置j,则next[i] = next[j] + 1,表示下一次
匹配失败时应该回退到这个位置。

8. 如果找不到这个位置j,说明前i个字符没有任何公共前后缀,此时next[i] = 0。

根据上述方法,可以依次计算出模式串的next数组的值。

ababaabab的next数组

ababaabab的next数组

ababaabab的next数组是指在字符串"ababaabab"中,每个字符所对应的最长前缀和后缀相等的长度。

next数组在字符串匹配算法中扮演着重要的角色,可以提高查找匹配的效率,下面将详细介绍ababaabab的next数组。

1. 定义在字符串匹配算法中,next数组是用来表示模式串中每个位置的最大相同前缀和后缀的长度。

具体来说,next[i]表示模式串中以第i个字符结尾的子串,其最大相同前缀和后缀的长度。

这个数组在KMP算法中被广泛应用,用来跳过不必要的比较操作,提高匹配效率。

2. ababaabab的next数组对于字符串"ababaabab"来说,其next数组如下所示:[-1, 0, 0, 1, 2, 3, 1, 1, 2, 0]。

下面就逐个字符来解释这个数组的含义。

3. 第一个字符'a'对于第一个字符'a'来说,由于它是字符串的开头,无前缀和后缀,所以next[0] = -1。

4. 第二个字符'b'对于第二个字符'b'来说,它之前只有一个字符'a',因此最大相同前缀和后缀的长度为0,所以next[1] = 0。

5. 第三个字符'a'对于第三个字符'a'来说,它之前有两个字符"ab",它的前缀和后缀都为'a',长度为1,所以next[2] = 1。

6. 第四个字符'b'对于第四个字符'b'来说,它之前有三个字符"aba",它的前缀和后缀都为'a',长度为1,所以next[3] = 1。

7. 第五个字符'a'对于第五个字符'a'来说,它之前有四个字符"abab",它的前缀和后缀为"ab",长度为2,所以next[4] = 2。

那些有关求解next数组的算法

那些有关求解next数组的算法

那些有关求解next数组的算法next数组的历史 有关字符串的模式匹配算法中,⽐较容易写出的是朴素的匹配算法也就是⼀种暴⼒求解⽅式,但是由于其时间复杂度为⼦串长度和主串长度的乘积,例如strlen(subStr) = n,strlen(mainStr) = m,则其时间复杂度为O(mn)。

为了能够得到更有效的匹配算法,D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此⼈们称它为克努特--莫⾥斯--普拉特操作(简称KMP 算法)。

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

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

这也即是KMP算法的设计思想。

next数组的求解思路 求next数组,next[j]表⽰,当模式串j位置与主串i位置处发⽣不匹配时,i指针不回溯,j指针回溯到next[j]的位置。

对于求next[j]有三种情况:1、j = 0时,next[j] = -1;//即模式串的第⼀个字符与主串i位置发⽣不匹配,应将i跳过当前位置,从下⼀个位置和模式串的第⼀个字符继续⽐较。

2、假设已知next[j] = k,即subStr[0,...,k-1] = subStr[j-k,j-1]。

当subStr[k] = subStr[j]时,也就是说模式串满⾜subStr[0,...,k] = subStr[j-k,j],可以得知next[j+1] = k + 1 = next[j] + 1;3、当subStr[k] != subStr[j]时,就需要从k位置之前去查找与subStr[j]匹配的位置,假设为j'。

这样问题⼜可以转化为第⼆种情况,即next[j+1] = next[j'] + 1 = k' + 1。

三种求解next数组的算法 但是如何去求解next数组呢?有关这个问题,我思考了很长时间,下⾯给出⼏种算法: 算法⼀,严格根据next数组的定义:1void getNext(char subStr[],int next[])2 {3int i = 1, j = i - 1,k = -1;4 next[0] = -1;5while (i < strlen(subStr))6 {7//k = -1时表⽰j指针回溯到第⼀个字符的位置8//subStr[k] == subStr[i-1]表⽰第k个字符和i - 1个字符相等,属于情况⼆9if (k == -1 || subStr[k] == subStr[i-1])10 {11 next[i] = k + 1;12 k = next[i];13 i++;14 }15//情况三,不相等的话,要回溯j指针,subStr[j'] = subStr[i-1]的位置j'16else17 {18int t = i - 2;19while (t>=0)20 {21if (subStr[t] == subStr[i - 1])22 {23 j = t;24break;25 }26 t--;27 }28if (t < 0)29 j = 0;30 k = next[j];31 }3233 }34 } 算法⼆,算法的设计思想和算法⼀⼤致相同void getNext(const char P[], int next[]){int q, k;int m = strlen(P);next[0] = -1;//模版字符串的第⼀个字符的最⼤前后缀长度为0for (q = 1; q < m; ++q)//for循环,从第⼆个字符开始,依次计算每⼀个字符对应的next值{k = next[q - 1];while (k > 0 && P[q - 1] != P[k])//迭代地求出P[0]···P[q]的最⼤的相同的前后缀长度k{k--;}if (P[q-1] == P[k])//如果相等,那么最⼤相同前后缀长度加1{k++;}if (k == -1)k = 0;next[q] = k;}} 算法三,更加优化的求解next数组的算法void getNext(const char subStr[], int next[]){int i = 1, j = -1;next[0] = -1;while (i < strlen(subStr)){//i从0开始的,属于情况⼆//j是前后缀长度if (j == -1 || subStr[i] == subStr[j]){i++;j++;next[i] = j;}//情况三,不同则j指针回溯elsej = next[j];}} 现在来进⾏总结⼀下,对于算法⼀和算法⼆来说,它们的时间复杂度是⼀样的,但是相对于算法三来说,虽然不如算法三⾼效,但是⽐较容易理解!PS:如果有误的地⽅,请指出,共同进步!。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

详解KMP算法中Next数组的求法
例如:
1 2 3 4 5 6 7 8
模式串 a b a a b c a c
next值 0 1 1 2 2 3 1 2
next数组的求解方法是:第一位的next值为0,第二位的next值为1,后面求解每一位的next值时,根据前一位进行比较。

首先将前一位与其next值对应的内容进行比较,如果相等,则该位的next值就是前一位的next值加上1;如果不等,向前继续寻找next值对应的内容来与前一位进行比较,直到找到某个位上内容的next值对应的内容与前一位相等为止,则这个位对应的值加上1即为需求的next值;如果找到第一位都没有找到与前一位相等的内容,那么需求的位上的next值即为1。

看起来很令人费解,利用上面的例子具体运算一遍。

1.前两位必定为0和1。

2.计算第三位的时候,看第二位b的next值,为1,则把b和1对应的a进行比较,不同,则第三位a的next的值为1,因为一直比到最前一位,都没有发生比较相同的现象。

3.计算第四位的时候,看第三位a的next值,为1,则把a和1对应的a进行比较,相同,则第四位a的next的值为第三位a的next值加上1。

为2。

因为是在第三位实现了其next值对应的值与第三位的值相同。

4.计算第五位的时候,看第四位a的next值,为2,则把a和2对应的b进行比较,不同,则再将b对应的next值1对应的a与第四位的a进行比较,相同,则第五位的next值为第二位b的next值加上1,为2。

因为是在第二位实现了其next值对应的值与第四位的值相同。

5.计算第六位的时候,看第五位b的next值,为2,则把b和2对应的b进行比较,相同,则第六位c的next值为第五位b的next值加上1,为3,因为是在第五位实现了其next值对应的值与第五位相同。

6.计算第七位的时候,看第六位c的next值,为3,则把c和3对应的a进行比较,不同,则再把第3位a的next值1对应的a与第六位c比较,仍然不同,则第七位的next值为1。

7.计算第八位的时候,看第七位a的next值,为1,则把a和1对应的a进行比较,相同,则第八位c的next值为第七位a的next值加上1,为2,因为是在第七位和实现了其next值对应的值与第七位相同。

相关文档
最新文档