蛮力法之串匹配问题---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

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决

JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法

《JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法》:本文主要介绍JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法,每种方法结合实例代码给大家介绍的非常... 目录引言:为什么"相等"判断如此重要?方法1:使用some()+includes()(适合小数组)方法2

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁