kmp算法求next 和nextval

合集下载

数据结构教程李春葆课后答案第4章串

数据结构教程李春葆课后答案第4章串

8. 采用顺序结构存储串,设计一个实现串通配符匹配的算法 pattern_index(),其中的 通配符只有‘?’ ,它可以和任一个字符匹配成功。例如,pattern_index("?re","there are") 返回的结果是 2。 解:采用 BF 算法的穷举法的思路,只需要增加对‘?’字符的处理功能。对应的算法 如下:
void maxsubstr(SqString s,SqString &t) { int maxi=0,maxlen=0,len,i,j,k; i=0; while (i<s.length) //从下标为 i 的字符开始 { j=i+1; //从 i 的下一个位置开始找重复子串 while (j<s.length) { if (s.data[i]==s.data[j]) //找一个子串,其起始下标为 i,长度为 len { len=1; for(k=1;s.data[i+k]==s.data[j+k];k++) len++; if (len>maxlen) //将较大长度者赋给 maxi 与 maxlen { maxi=i; maxlen=len; } j+=len; } else j++; } i++; //继续扫描第 i 字符之后的字符 } t.length=maxlen; //将最长重复子串赋给 t for (i=0;i<maxlen;i++) t.data[i]=s.data[maxi+i]; }
SqString CommChar(SqString s1,SqString s2) { SqString s3; int i,j,k=0; for (i=0;i<s1.length;i++) { for (j=0;j<s2.length;j++) if (s2.data[j]==s1.data[i]) break; if (j<s2.length) //s1.data[i]是公共字符 { s3.data[k]=s1.data[i]; k++; } } s3.length=k; return s3; }

kmp

kmp

2 KMP算法:KMP算法是由D.E.Knuth(克努特),J.H.Morris(莫里斯),V.R.Pratt(普拉特)等人共同提出的,该算法主要消除了主串指针(i指针)的回溯,利用已经得到的部分匹配结果将模式串右滑尽可能远的一段距离再继续比较,从而使算法效率有某种程度的提高,O(n+m)。

先从例子入手(p82):按Brute-Force算法i=i-j+2=2-2+2=2,j=1按Brute-Force算法i=i-j+2=2-1+2=3,j=1按Brute-Force算法i=i-j+2=8-6+2=4,j=1,但从已匹配的情况看,模式串在t[6]即“c”前的字符都是匹配的,再看已匹配的串“abaab”,t[1]t[2]与t[4]t[5]相同,那么,因为t[4]t[5]与原串s[6]s[7]匹配,所以t[1]t[2]必然与原串s[6]s[7]匹配,因此说t[3]可以直接与s[8]匹配,按KMP 算法i=8,j=3匹配成功。

从上例看出在匹配不成功时,主串指针i不动,j指针也不回到第一个位置,而是回到一个恰当的位置,如果这时让j指针回到第一个位置,就可能错过有效的匹配,所以在主串指针i不动的前提下,j指针回到哪个位置是问题的关键,既不能将j右移太大,而错过有效的匹配,另一方面,又要利用成功的匹配,将j右移尽可能地大,而提高匹配的效率,因此问题的关键是寻找模式串自身的规律。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////。

和直接比较若不满足和直接比较所以:满足:,设1i i 12112111112121s ),2(;s )1(""")"2(""")"1(""""t t j k t t t t t t t t s s t t t t s s s s k j k j k j k j i j i m n <<====-+-+----+-////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////设s=” s 1 s 2 ... s n ”, t=” t 1 t 2 ... t m ”,在匹配过程中,当s i ≠ t j (1≤i ≤n-m+1,1≤j ≤m)时,存在(前面的j-1个字符已匹配):” s i-j+1 ... s i-1 ” =” t 1 t 2 ... t j-1 ” (1) 若模式中存在可互相重叠的最长的真子串,满足: ” t 1 t 2 ... t k-1 ”=”t j-k+1 t j-k+2 ... t j-1 ” (2) 其中真子串最短可以是t 1 ,即 t 1。

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

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

计算模式串t的next数组和nextval数组的值next数组和nextval数组是用于字符串匹配算法中的KMP算法中的两个重要辅助数组。

KMP算法是一种高效的字符串模式匹配算法,它的主要思想是在匹配过程中,通过已经匹配的字串信息来避免不必要的回溯,从而提高匹配的效率。

next数组和nextval数组正是为了实现这个目的而设计的。

1. next数组的计算next数组是指模式串t中,每个字符对应的最长前缀子串和最长后缀子串的公共部分的长度。

定义next数组为next[i],表示模式串t中以第i个字符结束的子串的最长公共前缀子串和最长公共后缀子串的长度。

具体计算步骤如下:- 初始化next[0] = -1,next[1] = 0;-i=2,j=0;- 当i < t.length时,执行以下循环:- 如果t.charAt(i-1) == t.charAt(j),则next[i] = j + 1,i++,j++;- 如果t.charAt(i-1) != t.charAt(j):- 如果j == 0,则next[i] = 0,i++;- 如果j != 0,则j = next[j],继续比较t.charAt(i-1)和t.charAt(j)。

最终得到的next数组即为所求。

2. nextval数组的计算nextval数组是在next数组的基础上进行改进得到的,主要用于在匹配失败时的跳转操作。

定义nextval数组为nextval[i],表示当t.charAt(i)与主串中的字符不匹配时,需要从模式串t中的哪个位置开始继续匹配。

具体计算步骤如下:- 初始化nextval[0] = -1,nextval[1] = 0;-i=2,j=0;- 当i < t.length时,执行以下循环:- 如果t.charAt(i-1) == t.charAt(j),则nextval[i] =nextval[j];- 如果t.charAt(i-1) != t.charAt(j):- 如果next[j] == 0,则nextval[i] = 0;- 如果next[j] != 0,则j = next[j],继续比较t.charAt(i-1)和t.charAt(j)。

KMP算法计算next值和nextVal值

KMP算法计算next值和nextVal值

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

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和nextval值计算

KMP算法:next和nextval值计算

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数组求法的整理

关于KMP算法中next数组和nextVal数组求法的整理

关于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算法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;}其实在上⾯的匹配过程中,有很多⽐较是多余的。

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

next数组值的求解方法。

例如:
模式串a b a a b c a c
next值01122312
nextval值
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值对应的值与第七位相同。

在计算nextval之前要先弄明白,nextval是为了弥补next函数在某些情况下的缺陷而产生的,例如主串为“aaabaaaab”、模式串为“aaaab”那么,比较的时候就会发生一些浪费的情况:比较到主串以及模式串的第四位时,发现其值并不相等,据我们观察,我们可以直接从主串的第五位开始与模式串进行比较,而事实上,却进行了几次多余的比较。

使用nextval可以去除那些不必要的比较次数。

求nextval数组值有两种方法,一种是不依赖next数组值直接用观察法求得,一种方法是根据next数组值进行推理,两种方法均可使用,视更喜欢哪种方法而定。

我们使用例子“aaaab”来考查第一种方法。

1.试想,在进行模式匹配的过程中,将模式串“aaaab”与主串进行匹配的时候,如果第一位就没有吻合,即第一位就不是a,那么不用比较了,赶快挪到主串的下一位继续与模式串的第一位进行比较吧,这时,模式串并没有发生偏移,那么,模式串第一位a的nextval 值为0。

2.如果在匹配过程中,到第二位才发生不匹配现象,那么主串的第一位必定是a,而第二位必定不为a,既然知道第二位一定不为a,那么主串的第一、二两位就没有再进行比较的必要,直接跳到第三位来与模式串的第一位进行比较吧,同样,模式串也没有发生偏移,第二位的nextval值仍然为0。

3.第三位、第四位类似2的过程,均为0。

4.如果在匹配过程中,直到第五位才发生不匹配现象,那么主串的第一位到第四位必定为a,并且第五位必定不为b,可是第五位仍然有可能等于a。

如果万一第五位为a,那么既然前面四位均为a,所以,只要第六位为b,第一个字符串就匹配成功了。

所以,现在的情况下,就是看第五位究竟是不是a了。

所以发生了下面的比较:
123456
a a a a**
a a a a b
a a a a b
前面的三个a都不需要进行比较,只要确定主串中不等于b的那个位是否为a,即可以进行如下的比较:如果为a,则继续比较主串后面一位是否为b;如果不为a,则此次比较结束,继续将模式串的第一位去与主串的下一位进行比较。

由此看来,在模式串的第五位上,进行的比较偏移了4位(不进行偏移,直接比较下一位为0),故第五位b的nextval值为4。

我们可以利用第一个例子“abaabcac”对这种方法进行验证。

a的nextval值为0,因为如果主串的第一位不是a,那么没有再比较下去的必要,直接比较主串的第二位是否为a。

如果比较到主串的第二位才发生错误,则主串第一位肯定为a,第二位肯定不为b,此时不能直接跳到第三位进行比较,因为第二位还可能是a,所以对主串的第二位再进行一次比较,偏移了1位,故模式串第二位的nextval值为1。

以此类推,nextval值分别为:01021302。

其中第六位的nextval之所以为3,是因为,如果主串比较到第六位才发生不匹配现象,那么主串的前五位必定为“abaab”且第六位必定不是“c”,但第六位如果为“a”的话,那么我们就可以从模式串的第四位继续比较下去。

所以,这次比较为:
123 4 5678910 11 12
a b a a b*******
a b a a b c a c
而不是:
123 4 5678910 11 12
a b a a b*******
a b a a b c a
因为前两位a和b已经确定了,所以不需要再进行比较了。

所以模式串第六位的nextval 值为这次比较的偏移量3。

再来看求nextval数组值的第二种方法。

模式串a b a a b c a c
next值01122312
nextval值01021302
1.第一位的nextval值必定为0,第二位如果于第一位相同则为0,如果不同则为1。

2.第三位的next值为1,那么将第三位和第一位进行比较,均为a,相同,则,第三位的nextval值为0。

3.第四位的next值为2,那么将第四位和第二位进行比较,不同,则第四位的nextval 值为其next值,为2。

4.第五位的next值为2,那么将第五位和第二位进行比较,相同,第二位的next值为1,则继续将第二位与第一位进行比较,不同,则第五位的nextval值为第二位的next值,为1。

5.第六位的next值为3,那么将第六位和第三位进行比较,不同,则第六位的nextval 值为其next值,为3。

6.第七位的next值为1,那么将第七位和第一位进行比较,相同,则第七位的nextval 值为0。

7.第八位的next值为2,那么将第八位和第二位进行比较,不同,则第八位的nextval 值为其next值,为2。

在“aaaab”内进行验证。

模式串a a a a b
next值01234
nextval值00004。

相关文档
最新文档