KMP算法中next数组解析

 

KMP算法   next数组解析

本文很多词汇为 个人创造,如:最长匹配真前后缀、 次级最长匹配真前后缀 等。如有表述不清,请联系我。

 

接上篇:

next 数组 主要记录 子串 的 每一个前缀(按顺序)的 最长匹配真前后缀 的长度。

这里讲一下 求解原理。

数组从零开始,第一个数 “-1” ,代表不存在;(有的以 “0”,为起点代表空,这不矛盾,全加1 ,即为此格式)

此数组是一点点增长的,下一个数据依赖之前的数据。

举例子来描述原理:

   步骤1:

          当新的最后一个字母过来,和上一个字符串的 最长匹配真前后缀 的前缀后一位相同,则在数组对应位置,记录上的数是上一个 最长匹配真前后缀 长度 +1 ;即next数组前一个位置next[j] +1.  (新出现一个数,最长匹配真前后缀 的长度 最多 +1 ,对吧。下面会用到)

   步骤2 :

.如果新过来的字符和下一个位置不相符,如何处理?

    新出现一个数,最长匹配真前后缀 的长度 最多 +1

   那一定就是要把下面的串右移!!!即 最长匹配真前后缀 的长度 减少!!

   怎么移呢? 从头一个一个匹配? 可以,但并不优秀。

  之前next数组中记录的数据,是不是可以用起来呢?

  我们求的是匹配长度最大值,可以从可能的最大值依次往下验证,成立即为新的最大。

  

 划重点啦!!!    可能的最大值 是什么呢?

 就是从 次级最长匹配真前后缀  的下一位 匹配啊!!!

 举个例子: 子串  S =  "abcdabceabcdabc" ;  新字符 为 'd'; 示例如下:

'd' 和 'e' 失配后,存在可能性的就是 次级最长匹配真前后缀 且长度从大到小排列的,就是 图中的 S4 

此时只需要把 : ‘d’  和 次级最长匹配真前后缀  S4 后面的字符比较就可以了!

此处并不需要具体 字符串是什么,只需要知道位置即可,且next 数组存的就是这些!故此可以利用起来!

如果相同 执行步骤一,如果不相同执行步骤二。

解释:

      次级最长匹配真前后缀  是 字符串S 的第二长的  匹配真前后缀 ,同时也是 最长匹配真前后缀 (S3) 最长匹配真前后缀。

在此处,各位看官怎么理解都可以。不过似乎 理解为 ,最长匹配真前后缀 (S3) 最长匹配真前后缀 (-->S4),方便一些。便于理解这个代码中的循环处理。

   

附上代码:

void cal_next(char *str, int *next, int len)
{
    next[0] = -1;//next[0]初始化为-1,-1表示不存在相同的最大前缀和最大后缀
    int k = -1;//k初始化为-1
    for (int q = 1; q <= len-1; q++)
    {
        while (k > -1 && str[k + 1] != str[q])//如果下一个不同,那么k就变成next[k],注意next[k]是小于k的,无论k取任何值。
        {
            k = next[k];//往前回溯 //取其次级最长匹配真前后缀 的长度
            cout<< "k = " << k <<endl;
        }
        if (str[k + 1] == str[q])//如果相同,k++
        {
            k = k + 1;
        }
        next[q] = k;//这个是把算的k的值(就是相同的最大前缀和最大后缀长)赋给next[q]
        
        cout<<next[q]<<endl;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值