kmp算法next数组构造过程
- 格式:docx
- 大小:36.62 KB
- 文档页数:1
KMP算法计算next值和nextVal值
KMP算法:
给定⼀个主串S及⼀个模式串P,判断模式串是否为主串的⼦串;若是,返回匹配的第⼀个元素的位置(序号从1开始),否则返回0;这⾥先不写算法,仅仅计算next和nextVal值
那么计算时只⽤到⼦串,也就是模式串
这⾥模式串为:abaabcac
第⼀步将模式串写上序号,我们这⾥从1开始(有的从0开始,建议充1开始)
然后计算出maxL值,列出从第⼀个开始的⼦串,找出相等的前缀和后缀的个数
如果2>看不懂的话,看3>,
2>计算maxL值
所以maxL值
如果这个看不懂的话,看下⾯的3>
3>,如果2>看懂了这个就不⽤看了
依次类推4>计算next值
接下来将maxL复制⼀⾏,去掉最后⼀个数,在开头添加⼀个-1,向右平移⼀个格,然后每个值在加1的到next值
5>计算nextVal值,⾸先将第⼀个为0,然后看next和maxL是否相等(先计算不相等的)
当next和maxL不相等时,将next的值填⼊
当next和maxL相等时,填⼊对应序号为next值得nextVal值
所以整个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。
在字符串算法中,"next数组"是一个常用于KMP(Knuth-Morris-Pratt)算法的数据结构。
它记录了每个字符之前的模式串的"部分匹配长度"。
具体来说,对于字符串中的每个字符,next数组的值表示到目前为止(包括当前字符),最长的同时也是前缀和后缀的子串的长度。
例如,对于字符串 "ABABC",其next数组为 [0, 0, 1, 2],解释如下:
•对于A,没有前后缀匹配,所以next[0] = 0。
•对于B,同样没有前后缀匹配,所以next[1] = 0。
•对于A,有一个长度为1的前后缀匹配"A",所以next[2] = 1。
•对于B,有一个长度为2的前后缀匹配"AB",所以next[3] = 2。
•对于C,有一个长度为1的前后缀匹配"C",所以next[4] = 0。
这样,当我们在KMP算法中遇到一个字符时,我们可以使用next数组的值来确定下一个应该比较的字符的位置。
KMP算法:next和nextval值计算
KMP算法的next和nextval值计算
先看看next数据值的求解⽅法
例:下标从1开始(若题中给定下标为0开始,把所有值-1即可)
next数组的求解⽅法:根据前⼀个字符next,⼀直循环找到第⼀次匹配成功的下标,并把next=1;如果当前字符与下标1字符都不相同,next 值就为1(初始下标值)
第⼀位为0,第⼆位为1,
第三位:把前⼀个模式串字符b与下标next值所对应的字符⽐较,b 和a不同,next为1(初始下标值)
第四位:前⼀个,c c和a不同,next为1
第五位:a和a相同(下标为1)1+1=2
第六位:b和b相同(下标为2)2+1=3
第七位:a和c不同(下标为3),继续找,c下标为1,a和a相同(下标为1) 1+1=2
nextval数组求解⽅法:根据next数组的值作为下标找到第⼀个不同的字符,把它的下标作为nextval的值;否则继续循环⽐较,直到与第⼀个字符也相同,此时,nextval值为0
第⼀位为0,第⼆位为1,
第三位:(当前下标字符)c与a(next值1作为下标的字符进⾏⽐较),若不同则为初始下标值1
第四位: a和a相同(第⼀个字符),nextval值为0
第五位:b和b(下标为2),相同,继续⽐较,b的next为1,b和下标为1的⽐,即b和a⽐,不同,则nextval值为1
第六位:a和c(下标为3),不同,nextval为下标的值 3
第七位:a和b(下标为2),不同,nextval为下标的值 2
注:如果下标从0开始,只需把所有的next和nextval值-1就是。
关于KMP算法中next数组和nextVal数组求法的整理nextval例如:序号 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函数详解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 算法中,模式字符串的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中,每个前缀的最长相等真前后缀的长度数组。
这个数组在字符串匹配算法中非常重要,它可以帮助我们更快地进行字符串匹配,提高算法的效率。
为了更好地理解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的位置。
next数组的一般公式Next数组是一种常用的数据结构,它在字符串匹配、模式识别以及图像处理等领域中具有重要的应用。
本文将介绍Next数组的一般公式及其应用。
一、Next数组的定义和作用Next数组是一个用于字符串匹配的辅助数组,它记录了每个字符在匹配失败时应该跳转到的位置。
具体而言,对于一个长度为n的字符串S,Next[i]表示S中以第i个字符结尾的子串的最长公共前后缀的长度。
利用Next数组,我们可以在O(n)的时间复杂度内完成字符串匹配操作。
二、Next数组的计算方法Next数组的计算可以通过动态规划的方法来实现。
具体而言,我们可以通过以下递推关系式计算Next数组:1. 初始化Next[0] = -1,Next[1] = 0;2. 设j为当前位置,如果S[i-1] == S[j-1],则Next[i] = Next[j] + 1;3. 如果S[i-1] != S[j-1],则令j = Next[j],继续比较S[i-1]与S[j-1],直到找到满足S[i-1] == S[j-1]或者j = 0为止;4. 重复步骤2和3,直到计算完整个Next数组。
三、Next数组的应用1. 字符串匹配:通过Next数组,我们可以在主串中找到模式串的出现位置。
具体而言,我们可以在O(n)的时间复杂度内完成字符串匹配操作,这在大规模文本的搜索中非常高效。
2. 模式识别:在模式识别中,我们经常需要寻找图像或者信号中的特定模式。
利用Next数组,我们可以快速计算出模式的相似度或者匹配程度,从而实现模式识别的任务。
3. 图像处理:在图像处理中,我们经常需要进行特征提取或者图像比对。
Next数组可以帮助我们快速计算出图像中的特征序列,并进行相似度的比对,从而实现图像处理的任务。
四、Next数组的优化算法在实际应用中,为了进一步提高字符串匹配的效率,可以对Next数组的计算方法进行优化。
其中最著名的算法是KMP算法,它通过预处理得到一个优化后的Next数组,从而在匹配过程中减少了不必要的比较操作,提高了匹配效率。
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算法(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. 子串匹配:判断一个字符串是否是另一个字符串的子串。
字符串的next数组值-回复字符串的next数组是一种重要的数据结构,用于匹配字符串中的模式。
它的作用是在字符串匹配中快速确定模式的后续移动位置,从而提高匹配的效率。
本文将从定义、应用和实现等方面逐步讲解字符串的next数组值,希望对读者有所帮助。
首先,让我们来了解一下字符串的next数组是什么。
在字符串匹配中,我们经常需要查找一个模式在目标字符串中的位置。
而字符串的next数组就是为了加速这个过程而设计的。
它是一个数组,长度与模式字符串的长度相同。
next数组的每个元素值是一个整数,表示指定位置之前字符串的“最长相同前后缀”长度。
这里的“最长相同前后缀”指的是模式字符串中以该位置字符结尾的前缀子串,与以该位置字符开头的后缀子串相同的最大长度。
了解了next数组的定义后,下面我们来看一下它的应用。
在字符串匹配算法中,KMP算法是一种常用的算法,而next数组就是KMP算法的核心。
KMP算法通过利用next数组的特性,能够在不遍历所有字符的情况下快速移动模式串,从而提高了匹配的效率。
特别是在处理大规模文本匹配时,可以减少遍历的次数,降低了时间复杂度,极大地提高了匹配的速度。
接下来,我们来讨论一下next数组的实现。
在KMP算法中,next数组的构建需要一定的算法思路。
下面是一种常用的构建方式:首先,我们定义两个指针i和j,分别指向模式串的前缀和后缀。
初始化时,i=0,j=-1,next[0]的值为-1。
然后,我们进入一个循环,不断更新next数组的值。
在循环中,先判断j是否等于-1,如果等于-1,表示i已经移到了模式串的开头,需要更新i 和j的值。
这时,i++,j++,并且next[i]的值为j。
接下来,如果模式串i位置的字符和j位置的字符匹配,则继续更新i和j 的值,i++,j++,并且next[i]的值为j。
如果模式串i位置的字符和j位置的字符不匹配,则需要回溯。
这里有个重要的思路,即如果next[j]的值为k,表示模式串在j位置之前存在一个最长相同前后缀,那么在模式串i位置和模式串j位置匹配失败时,可以直接将j指向next[j],继续进行匹配。
int next[110];//kmp模板//注意这里next在打出时是从1开始的,但是字符串中存的是从0开始void get_next(char t[])//获得next数组,相当于自己和自己匹配{int i,j;i=1;next[1]=0;//利用递归打的表,要初始化j=0;//这里j必须是比i小的while(i<strlen(t)){if(j==0||t[i-1]==t[j-1])//这里next中的下标要减一再用在字符串中{i++;j++;if(t[i-1]!=t[j-1])next[i]=j;elsenext[i]=next[j];//这里是一种优化}elsej=next[j];//向前找}}int kmp(char s[],char t[]){get_next(t);int i,j;int lens,lent;i=1;//从1开始j=1;while(i<=strlen(s)&&j<=strlen(t)){if(j==0||s[i-1]==t[j-1]){i++;j++;}elsej=next[j];}if(j>strlen(t))return 1;//这里也可以返回i-strlen(t)来获得匹配在主串中开始的位置elsereturn 0;}Poj1226#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>#include<string>char ss[110][110];char ss0[110];char pp[110],ppf[110];int next[110];int main(){int i,j;int n;int t;int len,len0;int num;int flag;int max;scanf("%d",&t);while(t--){len=120;scanf("%d",&n);for(i=0;i<n;i++){scanf("%s",ss[i]);len0=strlen(ss[i]);if(len0<len){len=len0;strcpy(ss0,ss[i]);}}// printf("%s 5555\n",ss0);flag=0;for(int k=len;k>=1;k--){for(i=0;i<len&&i+k-1<len;i++){int tt=0;for(j=i;j<=i+k-1;j++){pp[tt]=ss0[j];tt++;}pp[tt]='\0';for(j=0;j<tt;j++){ppf[tt-1-j]=pp[j];}ppf[tt]='\0';//num=0;for(j=0;j<n;j++){if(!(strstr(ss[j],pp)||strstr(ss[j],ppf)))//直接利用c++中的看某字符串是否在另一个串中出现break;}if(j==n){max=k;flag=1;break;}}if(flag==1)break;}if(flag==0)printf("0\n");elseprintf("%d\n",max);}system("pause");}。
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满⾜上⾯等式。
"Next 数组" 通常用于 KMP 字符串匹配算法中,它用于加速字符串匹配过程中的跳转操作。
Next 数组的生成方式是根据模式串本身的特征,计算出一个部分匹配值(Partial Match Table),并利用这个部分匹配值构造出 Next 数组。
下面是生成
Next 数组的基本方式:
1.初始化 Next 数组:将 Next 数组初始化为全为 0 的数组。
2.计算部分匹配值:遍历模式串,计算每个位置的最长相等前缀后缀的长度,
即部分匹配值。
这个值表示当模式串和文本串部分匹配时,下一步应该比较
的模式串的位置。
3.生成 Next 数组:根据计算出的部分匹配值,构造出 Next 数组。
Next 数组
的值等于部分匹配值减去 1,或者是根据部分匹配值的规律得出。
生成 Next 数组的算法步骤可以简单描述为:
生成 Next 数组的具体实现取决于使用的编程语言和算法实现方式。
在实际的编程
实现中,通常会使用循环和条件判断来计算和构造 Next 数组。
这个过程可以通过
一些算法模板或者相关的代码库来实现,比如在 C/C++ 中实现 KMP 算法时,可以通过编写相应的函数来生成 Next 数组。
总的来说,Next 数组的生成方式是根据模式串的部分匹配值构造出一个辅助数组,用于加速 KMP 算法中的模式匹配过程。
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,相等。
C语言输出模式串对应的next数组一、概述在字符串匹配算法中,next数组是KMP算法中的一个关键部分。
KMP算法是一种高效的字符串匹配算法,通过预处理模式串,可以达到快速匹配的目的。
而next数组就是用来存储模式串中每个位置对应的最长公共前缀和后缀的长度,它是KMP算法的核心。
二、KMP算法原理KMP算法是一种改进的字符串匹配算法,它的核心思想是利用已知信息尽量减少比较的次数。
在传统的字符串匹配算法中,每次失配后都是回溯到模式串的起始位置重新开始比较,而KMP算法通过预处理模式串,得到模式串的next数组,可以在失配时根据next数组的值进行跳转,从而达到减少比较次数的目的。
三、next数组的计算1. 初始化next数组在计算next数组之前,首先需要初始化next数组,即将第一个位置的值置为-1,第二个位置的值置为0。
这两个位置的值是KMP算法中的边界条件,用来判断是否需要移动模式串。
2. 计算next数组的值从第三个位置开始计算next数组的值。
假设当前位置为i,已知next[i-1]的值,需要计算next[i]的值。
首先假设模式串的前缀和后缀分别为P[0, i-1]和P[1, i-1],即P的第一个字符到第i-1个字符和P的第二个字符到第i个字符。
如果P[i-1]和P[next[i-1]]相等,则next[i] = next[i-1] + 1;如果不相等,则需要继续向前寻找更短的相等前缀和后缀。
假设P[0, next[i-1]]和P[i-next[i-1], i-1]分别表示P的前next[i-1]+1个字符和后next[i-1]+1个字符。
如果P[next[i-1]]和P[i-1]相等,则next[i] = next[i-1] + 1;否则继续向前寻找更短的相等前缀和后缀,直到找到相等的前缀和后缀或者next[i] = 0。
以此类推,直到计算出整个next数组的值。
四、C语言实现下面用C语言来实现计算模式串对应的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个字符不匹配。
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数组的值。
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数组,可以快速确定模式串的移动位置,
从而提高匹配效率。