KMP算法中的next[i]和nextval[i]的规律回顾

一 概述

KMP算法是为了优化朴素匹配模式中的主串指针回溯问题,此过程中回产生一个next[i]数组,而KMP优化算法是优化模式串指针的回溯问题,此过程中回产生一个nextval[i]数组。

二 KMP算法之数组之next[i]

当模式串中的第j个字符匹配失败,由前1~j-1个字符组成的串记为S,则:next[j] = S的最长相等前后缀长度+1。

如模式串'aababaaaba'。串的下标从1开始。

此时字符串中第一个字母a对应next[1] = 0 ;第二个字母a对应next[2] = 0+1 = 1,其中0表示第二个字母a之前的字符串中前后缀相等的情况为0;

01        

注意:当个字符a中是不存在前后缀。

第三个字符b之前的字符串为'aa'存在相同的前缀和后缀'a',所以next[2] = 1 + 1 = 2。 

012       

第四个字符a之前存在的字符串为'aab',不存在相同的前后缀,所以next[3] = 0 + 1 = 1。

0121      

第五个字符b之前存在的字符串为'aaba',存在最长的相同前后缀'a',所以next[4] = 1 + 1 = 2。

01212     

第六个字符a之前存在的字符串为'aabab',不存在相同的前后缀,所以next[5] = 0 + 1 = 1。

012121    

第七个字符a之前存在的字符串为'aababa',存在最长的相同前后缀为'a',所以next[6] = 1 + 1 = 2。

0121212   

第八个字符a之前存在的字符串为'aababaa',存在最长的相同前后缀'aa',所以next[7] = 2 + 1 = 3。

01212123  

第九个字符b之前存在的字符串为'aababaaa',存在最长的相同前后缀'aa',所以next[8] = 2 + 1 = 3。

012121233 

第十个字符a之前存在的字符串为'aababaaab',存在最长的相同前后缀为'aab'  所以next[9] = 3 + 1 = 4。

0121212334

三 KMP算法优化后的数组nextval[i]

1. KMP算法会存在的不足:

主串为gogoodgooglegooglo而模式串为google时,当比对到以下情况:

gogoodgooglegooglo
////google////////////////////

当比对到模式串google中的第二个g同gogoodgooglegooglo中的d对应上时,将模式串中的google中的第一个g移动到与gogoodgooglegooglo中d的对应位置。

gogoodgooglegooglo
//////////google//////////////

由于第一次中已经知道了d与g是不相同的,所以这种比较是多余的,所以通过nextval[i]对KMP算法进行优化。

如模式串'aababaaaba'。

序号j12345678910
模式串aababaaaba
next[i]0121212334
nextval[i]          

KMP算法优化:当子串和模式串不匹配时nextval[j] = j;

2. nextval数组的求法

先算出next数组,先令nextval[1] = 0;

for(int j = 2; j <= T.length; j++) {
    if(T.ch[next[i]] == T.ch[i])
        nextval[j] = nextval[next[j]];
    else 
        nextval[j] = next[j];
}

1. 对于第一个字符'a'的nextval[1] = 0;

对于第二个字符'a'的next[2] = 1,所以对应序号为1的元素'a',根据

if(T.ch[next[i]] == T.ch[i])
nextval[j] = nextval[next[j]];

将nextval[1]赋值给nextval[2];

2. 对于第三个字符'b'的next[3] = 2,所以对应序号为2的元素'b',根据

if(T.ch[next[i]] != T.ch[i])
nextval[j] = next[j];

所以将next[3]赋值给nextval[3];

由此同理可得,最后的结果如下:

序号j12345678910
模式串aababaaaba
next[i]0121212334
nextval[i]0020200320

此处总结了KMP算法的next[]和nextval[]的计算,后续有所优化继续补充。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值