当前位置:网站首页 > 技术博客 > 正文

求next数组的算法



写这篇文章,真的花了我很多功夫,希望能够对看到的大家有所帮助啦

首先,KMP算法的作用是进行模式串的匹配

也就是对于一个已知的长字符串t,我们在其中找到,与模式串m完全相同的部分,并且返回相同部分的首数组标号

采用BF算法,能够非常直观求出匹配位置,但是由于指针回溯,进行了多余的比较,非常缓慢

这样就有了KMP算法的诞生
alt

下文中,我们将待比较的字符串,存入下面这样的结构体中:

 

我们发现,可以减少BF算法比较次数的原因在于,BF算法中,每一次模式串的指针回移太长了

我们发现将如下图的指针i和j全部回移,归位,就会多进行很多无用的比较

alt

我们之所以知道多余的回退是没有用的,是由模式串本身的特性决定的

我们已知,即使在出现不匹配时,不匹配处的左侧的字符串和主串对应位置,是相同,或者说匹配的.

就像上图中一样,进行到第三步的时候(图中标错了),前面的"ana"在主串和模式串中,都是相同的

我们可以考虑引入一个概念,也就是"最大公共前后缀",假设其位数为n位

也就是从该部分匹配串的第一位开始往后数n位,和此部分匹配串的最后一位开始往前数n位,两者完全相同

当然也会有"次大公共前后缀",但是如果是次大的话,就会出现回移过少,漏掉了可能性的情况

我们必须考虑最大的公共前后缀,让j指针回移最多,并且不会漏掉可能性,从而最大程度得节约步骤和考虑全面.这样一个最佳位置,其实就是最大公共前后缀的位数.

使用KMP的过程中,我们不回移i指针,仅仅将j指针回移到左边的"部分匹配串"的"最大公共前后缀"中的前缀的后一位的位置,重新继续与主串匹配

我们的next数组,与模式串的长度相同

其中,记录的就是当前位置左边的"部分匹配串"的最大公共子串长度n

也是j指针接下来要移动到的位置,在下图中已经说明了.

alt

下面的代码是用上图中的第二种编号方法写出的:

 

alt

alt

alt

 

为什么要引入nextval数组呢?

其实上文中认为next数组就是模式串回退的最佳位置,其实是不对的

next数组中保存的是"当前位置左边部分匹配串"的"最大公共前后缀"的位数n或者是n-1(没有本质差别)

虽然next数组能用,它确实大大优化了模式串的后移位数,并且不会遗漏正确结果,但是它仍不是,效率最高的后移位置
alt

alt

为什么nextval数组更加优化了?
alt

nextval数组是怎样得到的?

是在已知next数组的基础上,进行如下规则的判断得到的:
alt

求next和nextval数组的例子如下,可以跟着线条多画几遍,就能够熟练了:

就拿下图中eg2中数据为例,在模式串为0位置处,next和nextval数组的值都必然是-1,这是默认不变的

  • 首先,求next数组的方法就是:

首先以位置5为例:

要求出位置5的next值,必须要看位置5-1(=4)的next值

比较位置4的字符和next [ 4 ] (=1)位置的字符,如果相等,则5位置存入next[4]+1

若不等,则比较位置4字符和next [ next [ 4 ] ] (=0)的字符,如果相等,则存入next [ next [ 4 ] ] +1(=1)

然后,以位置7为例,考虑一种特殊情况,也就是到了最后也没有匹配成功的情况:

求7看6,'b’为标准,向前找到2号c,不匹配

再向前找到0号’a’,仍然不匹配,则直接返回(-1+1)=0

总结一下求next值方法!!!

前位字符为标准,next值作模串标号向前跳,匹配则返回该标号加1,不匹配继续向前跳,0号还不匹配直接返回0

  • 在next数组的基础上,求nextval的方法就是:

以位置8为例:

求nextval数组,直接以当前位置的next值作为标号,向前跳一位,比较当前位和前跳位字符

1.匹配,则当前位nextval值,等于前跳位nextval值

2.不匹配,则当前为nextval值,直接等于当前位next值

总结一下求nextval值方法!!!

当前位字符为标准,next值为模串标号向前跳一位,匹配nextval值等于前跳位,不匹配当前位next值直接落下来

alt

 

将匹配起始点结果存入P数组中

可以灵活根据需要,修改这段代码,可以参考以下例子:

https://blog.nowcoder.net/n/2dcba84e8096a41196ee5c6506

调整之后,就能够存入符合特定要求的匹配串了

 

                            

版权声明


相关文章:

  • 用idea创建java项目2025-03-07 08:01:03
  • genesys安装教程2025-03-07 08:01:03
  • api接口测试工具2025-03-07 08:01:03
  • html5 form标签2025-03-07 08:01:03
  • rbac权限设计2025-03-07 08:01:03
  • java orm框架性能比较2025-03-07 08:01:03
  • 数据库开发实战2025-03-07 08:01:03
  • 性能测试平台2025-03-07 08:01:03
  • java中网络编程三要素2025-03-07 08:01:03
  • c语言中perror是什么意思2025-03-07 08:01:03