蛮力法之串匹配问题---kmp算法中真/后缀作用及next数组计算

本文主要是介绍蛮力法之串匹配问题---kmp算法中真/后缀作用及next数组计算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在源串S中搜索目标串T时,利用串匹配的暴力求解方法,在求解的过程中,我们分析得到简化该问题求解过程的关键步骤,也即kmp算法的核心思想:如何在某趟S[i]和T[j]匹配失败时,下标i不回溯,下标j回溯到某个位置k,下一趟搜索时,从T[k]和S[i]开始比较。这样可以使得算法复杂度降低到O(n),其中n为源串S的长度。

一、什么是真前缀和真后缀

真前缀就是对T[j]来说,使得T[0]~T[k-1]=T[j-k]~T[j-1],k取最大值时的子串T[0]~T[k-1],同理

真后缀就是对T[j]来说,使得T[0]~T[k-1]=T[j-k]~T[j-1],k取最大值时的子串T[j-k]~T[j-1]

直观来说就是,就是在子串T[0]~T[j-1]中,k从取值范围[0,(j-1)/2]中逐渐增大,使得

从下标0开始向后增加构建子串T1=T[0]

                                                 T1=T[0]T[1]

                                                 T1=T[0]T[1]T[2]

                                                 ......

                                                 T1=T[0]T[1]T[2]···T[k-1]

从下标j-1开始向前减小构建子串T2=T[j-1]

                                                   T2=T[j-2]T[j-1]

                                                   T2=T[j-3]T[j-2]T[j-1]

                                                   ......

                                                   T2=T[j-k]···T[j-3]T[j-2]T[j-1]

在构建子串T1,T2的过程中,依次比较

T1=T[0]是否与T2=T[j-1]相等:若相等,进行下一轮的T1,T2的构建与比较;

T1=T[0]T[1]是否与T2=T[j-2]T[j-1]相等:若相等,再进行下一轮的T1,T2的构建与比较;

依次类推,直到k取得最大值(j-1)/2时结束;

T1,T2的比较过程中,如果出现T1不等于T2的情况,则T1,T2的构建与比较过程结束,k取使得T1=T2时的最大值,此时对应的

真前缀就是T[0]~T[k-1]

真后缀就是T[j-k]~T[j-1]


二、为什么要计算真前缀和真后缀

在如下的搜索比较时出现S[i]不等于T[j]:

S[0]S[1]··········S[i-3]S[i-2]S[i-1]S[i]··········S[n-3]S[n-2]S[n-1]

                T[0]·········T[j-2]T[j-1]T[j]······T[m-1]

显然字符串 T[0]~T[j-2]T[j-1]等于字符串S[i-j]~S[i-2]S[i-1],它们的长度为j

显然它们的子串T[j-k]~T[j-1]等于S[i-k]~S[i-1],它们的长度为k

这时,利用T[j]的真前缀和真后缀T[0]~T[k-1]=T[j-k]~T[j-1]

所以T[0]~T[k-1]等于S[i-k]~S[i-1]

根据KMP算法思想,i不动,j需要回溯到某一个位置,根据上面的分析,j需要回溯到位置k,即下一次比较从S[i]和T[k]开始,也即:

S[0]S[1]··········S[i-3]S[i-2]S[i-1]S[i]··········S[n-3]S[n-2]S[n-1]

                             T[0]····T[k-1]T[k]···T[j-1]T[j]···T[m-1]

这也体现了真前缀和真后缀得作用。


三、next数组计算

若已找到T[j]的真前缀和真后缀,也即T[0]~T[k-1]=T[j-k]~T[j-1],在求T[j+1]真前缀和真后缀时,分两种情况:

(1)T[k]=T[j],则T[j+1]的真前缀和真后缀为T[0]~T[k-1]T[k]=T[j-k]~T[j-1]T[j]

(2)T[k]不等于T[j],那么需要在T[0]~T[j]中寻找真前缀和真后缀,分析得到如下结论:

(i)因为T[0]~T[k-1]=T[j-k]~T[j-1],所以真前缀和真后缀得定义可以推断出字符串T[0]~T[k-1]关于T[k]T[j-k]~T[j-1]关于T[j]真前缀和真后缀是一样的,所以得到结论T[0]~T[k-1]关于T[k]的真前缀等于T[j-k]~T[j-1]关于T[j]的真后缀;

(ii)结论:next[k]的值为T[0]~T[k-1]真前缀和真后缀的字符串长度,正如next[j]的值为字符串T[0]~T[k-1]的长度;

根据以上(i)和(ii)结论,

k=next[k]

若T[k]=T[j],也即T[next[k]]=T[j],则next[j+1]=k+1,解释如下:

根据结论(i)可以得到T[0]~T[next[k]-1]=T[j-next[k]]~T[j-1],又因为T[next[k]]=T[j],可以得到T[0]~T[next[k]-1]T[next[k]]=T[j-next[k]]~T[j-1]T[j]该式满足T[0]~T[j+1]关于真前缀和真后缀的定义,所以next[j+1]=k+1;

T[k]不等于T[j]则继续寻找T[0]~T[next[k]]的真前缀,此时继续令k=next[k],

直到T[k]=T[j](此时next[j+1]=k+1),

或者直到k=-1(此时next[j+1]=0)。

根据如上讨论可以计算得到next数组。



这篇关于蛮力法之串匹配问题---kmp算法中真/后缀作用及next数组计算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933694

相关文章

windows和Linux使用命令行计算文件的MD5值

《windows和Linux使用命令行计算文件的MD5值》在Windows和Linux系统中,您可以使用命令行(终端或命令提示符)来计算文件的MD5值,文章介绍了在Windows和Linux/macO... 目录在Windows上:在linux或MACOS上:总结在Windows上:可以使用certuti

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

MyBatis模糊查询报错:ParserException: not supported.pos 问题解决

《MyBatis模糊查询报错:ParserException:notsupported.pos问题解决》本文主要介绍了MyBatis模糊查询报错:ParserException:notsuppo... 目录问题描述问题根源错误SQL解析逻辑深层原因分析三种解决方案方案一:使用CONCAT函数(推荐)方案二:

Redis 热 key 和大 key 问题小结

《Redis热key和大key问题小结》:本文主要介绍Redis热key和大key问题小结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、什么是 Redis 热 key?热 key(Hot Key)定义: 热 key 常见表现:热 key 的风险:二、

IntelliJ IDEA 中配置 Spring MVC 环境的详细步骤及问题解决

《IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决》:本文主要介绍IntelliJIDEA中配置SpringMVC环境的详细步骤及问题解决,本文分步骤结合实例给大... 目录步骤 1:创建 Maven Web 项目步骤 2:添加 Spring MVC 依赖1、保存后执行2、将新的依赖

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

SpringBoot项目中报错The field screenShot exceeds its maximum permitted size of 1048576 bytes.的问题及解决

《SpringBoot项目中报错ThefieldscreenShotexceedsitsmaximumpermittedsizeof1048576bytes.的问题及解决》这篇文章... 目录项目场景问题描述原因分析解决方案总结项目场景javascript提示:项目相关背景:项目场景:基于Spring

解决Maven项目idea找不到本地仓库jar包问题以及使用mvn install:install-file

《解决Maven项目idea找不到本地仓库jar包问题以及使用mvninstall:install-file》:本文主要介绍解决Maven项目idea找不到本地仓库jar包问题以及使用mvnin... 目录Maven项目idea找不到本地仓库jar包以及使用mvn install:install-file基