改进KMP算法及求解nextval数组

书接上文,图解KMP算法及如何求next数组,在知道了什么是KMP算法及如何求解next数组之后,我们来讨论一下KMP算法的改进空间。

KMP算法的问题及改进

问题

假设有这样一个模式串"aaaaaaaaa",它的next数组是:[-1, 0, 1, 2, 3, 4, 5, 6, 7]。假设在模式串的最后一位发生了不匹配,例如下图的情况:
在这里插入图片描述
此时,如果按照KMP算法,需要从索引为7的元素开始依次向前比较,发现这些元素都不匹配,一直到索引为0时才停止。
虽然上面举的例子是一种比较极端的情况,但我们也可以发现KMP算法的一个不足之处:当发生不匹配时,我们可以根据next数组知道如何移动模式串,但是并没有考虑当前元素与移动后进行比较的元素的关系。

改进方法

要解决上面提出的问题也很简单,只需要在计算next数组时将当前元素也纳入考虑即可。
假设模式串为p,当前元素的索引为j:如果p[j] == p[next[j]],说明一旦当前元素和主串发生不匹配时,我们移动模式串后进行比较,也一定是不匹配的。因此,在这种情况下我们可以不用比较p[next[j]]是否和主串中对应元素相等,而是依次寻找next[j]不同时要比较的元素中和当前元素不同的,将找到的元素作为移动模式串的依据。

求nextval数组

在对KMP算法进行改进后计算得到的数组我们一般称为nextval数组,它的计算过程如下:

int[] getNextval(String pattern){
        int length = pattern.length();
        int[] nextval = new int[length];
        nextval[0] = -1;
        int i = -1, j = 0;
        while (j < length - 1){
            if (i == -1 || pattern.charAt(i) == pattern.charAt(j)){
                i++;
                j++;
                //与求next数组不同的地方在于要考虑当前元素的情况
                if (pattern.charAt(i) == pattern.charAt(j)){
                    nextval[j] = nextval[i];
                }else {
                    nextval[j] = i;
                }
            }
            else {
                i = nextval[i];
            }
        }
        return nextval;
    }

可见,nextval数组的计算方式基本和next数组一样,唯一的区别在于如果当前元素和要跳转的元素相同时,我们转而寻找要跳转的元素不匹配时要继续跳转的元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值