KMP算法的动态规划解说
理解我接下来所说的东西,需要大家懂得简单的动态规划。
KMP大家都不陌生了,但是其中计算next数组总是搞不明白,我想有很多人和我一样。所以这里用动态规划的思路去描述一下这个问题。
模式串P=c[1]c[2]......c[n]
先设几个符号:
suffix(S): S的所有后缀的集合
prefix(S): S的所有前缀的集合
例如:suffix("abcd") = {"","d", "cd", "bcd"}
prefix("abcd") = {"","a", "ab", "abc"}
看到,在这两个集合都除去了"abcd"本身。
真对P定义next的意义:next[i]代表的意义是suffix(c[1]c[2]......c[i])与prefix(c[1]c[2]......c[i])两个集合中最长相同串的长度(不包括串c[1]c[2]......c[i])。那么如何计算next呢?其实这个计算过程类似动态规划的转移过程,从初始状态,不断的根据转移方程计算,直至计算出所有的可达状态。
那么状态怎么定义?初始条件是什么?
设两个游标p1,p2, p1,p2构成的位置对为状态<p1,p2>,例如p1在i位置,p2在j位置,i<j,那么状态<i, j>就代表c[1]c[2]......c[i]=c[j-i+1]c[j-i+2]......c[j],即串的前i个字符与后i个字符相同。之后我们根据<i,j>推出<i',j+1>。我们依次计算<i1, 1>,<i2,2>,......,<in,n>。设LMAX(<i, j>)=i,通过上面对next的定义,我们可知next[j]=MAX{LMAX(<i,j>)|0<=i<j}。
初始化的条件为 next[1] = LMAX(<0, 1>) = 0。假设我们当前所在的状态为<i, j>,那么如何推出<i',j+1>呢?这必须得看c[i+1]与c[j+1]的关系,如果c[i+1]=c[j+1],那么我们到达<i+1,j+1>的状态;如果c[i+1]!=c[j+1],那么我们得根据所有可能的<i', j>状态,判断c[i'+1]=c[j+1]是否成立,如果成立就到达<i'+1,j+1>状态。那么,我们如何找到这些合法的<i',j>状态呢?很庆幸,因为next数组中天然的保存了我们需要的信息。当我们到达<i,j>这个状态并且发现c[i+1]!=c[j+1],那么下一个尝试的状态将是<next[i], j>,看看c[next[i]+1]=c[j+1]是否成立。而且我们发现,只要按照i,next[i],next[next[i]]......这样下去找到第一个能够符合转移条件的状态就OK了,如果没有一个能够使之转移的状态,就说明没有一个前缀和当前的某个后缀是相等的,那么直接跳转到<0, j+1>这个状态。
举个例子吧: S=abcababc为了方便理解,在S前加一个通配符$$abcababc <0, 1> next[1]=0 ||$abcababc <0, 2> next[2]=0 | | $abcababc <0, 3> next[3]=0 | |$abcababc <1, 4> next[4]=1| | $abcababc <2, 5> next[5]=2| |下一步s[3]!=s[6],这将尝试状态<next[3],j>=<0,j>,使之转移到下面的状态$abcababc <1, 6> next[6]=1| | $abcababc <2, 7> next[7]=2| |$abcababc <3, 8> next[8]=3| |
到此,有的同学又有疑问了,人家KMP定义的next[i]的意义和你的也不一样呀。对,确实不一样。
KMP中对next[i]的定义为:设文本串为T,模式串为P,p[i]!=T[j]时,应该用p[?]与T[j]进行比较。
对应于上例,得到的next数组值应为
KMP的next: -1 1 1 1 2 3 2 3
我们的next: 0 0 0 1 2 1 2 3
怎么通过我们的next获取到正确的next呢?非常简单,从后往前循环做next[i] = next[i-1]+1,之后next[1]=-1就哦了。
KMP算法的动态规划解说相关推荐
- 【Java数据结构与算法】第十八章 动态规划和KMP算法
第十八章 动态规划和KMP算法 文章目录 第十八章 动态规划和KMP算法 一.动态规划 1.介绍 1.爬楼问题 2.扔鸡蛋问题 3.背包问题 二.KMP算法 1.引入 2.介绍 2.代码实现 一.动态 ...
- 1道动态规划(搬箱子)、KMP算法、图(Prim算法)、1道哈夫曼树
1.最长递增子序列 华华要给厂里进一批新箱子共n个(n<=500),编号为1到n,用一个正整数ai(1<=ai<=10000)(1<=i<=n)来表示编号为i的箱子的高度 ...
- 【★】KMP算法完整教程
2019独角兽企业重金招聘Python工程师标准>>> KMP算法完整教程 全称: Knuth_Morris_Pratt ...
- KMP算法具体解释(转)
作者:July. 出处:http://blog.csdn.net/v_JULY_v/. 引记 此前一天,一位MS的朋友邀我一起去与他讨论高速排序,红黑树,字典树,B树.后缀树,包含KMP算法,只有在解 ...
- KMP算法之 好理解的模板
主要作用:能够在线性复杂度内求出一个串在另一个串的所有匹配位置. 说明:设模板串是 pattern, 令 next[i] = max{k|[pattern[0..k−1] = pattern[i−k+ ...
- KMP算法的Next数组详解(转)
转载请注明来源,并包含相关链接. 网上有很多讲解KMP算法的博客,我就不浪费时间再写一份了.直接推荐一个当初我入门时看的博客吧: http://www.cnblogs.com/yjiyjige/p/3 ...
- 详解KMP算法原理,以及完整java与C++实现
点击此处学习更多算法与通信知识 作者 | labuladong 来源 | labuladong KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法,效率很高,但是确实 ...
- 字符串匹配(KMP 算法 含代码)
主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知 ...
- KMP算法的java实现
package com.trs.utils;public class KMPStr {/** 在KMP算法中,最难求的就是next函数,如何理解next函数是一个难题,特别是k=next[k],这里* ...
最新文章
- 除了数据属性,Vue 实例还提供了一些有用的实例属性与方法。它们都有前缀 $,以便与用户定义的属性区分开来。
- ant文件放在ps的哪里_ant design vue按需导入icons
- ubuntu 20.04 安装circos
- C++并发编程实战(豆瓣评分5.4)
- 利用指针编程实现:删除一个字符串中的所有空格 c语言,C语言必考100题解析汇报...
- leetcode - 516. 最长回文子序列
- System.BadImageFormatException: 试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)...
- mybatis一个怪异的问题: Invalid bound statement (not found)
- 处理器好点是否上网就快些?
- 程序员为什么要懂物联网?
- node.js 框架基本功能
- 草根站长的创业路:说说这两年的创业经历
- wincc安装信息服务器,WinCC 7.4软件不会安装?怎么授权?一文教会你
- opensips服务端搭建
- 阻止原生输入中文拼音途中会触发input方法的问题
- uniapp html5+ plus蓝牙连接电子秤
- ettercap进行简单的arp欺骗和中间人攻击
- 条码打印软件引用其他对象内容的方法
- 飞天 AI 平台重磅发布!阿里拥抱 AI 这五年
- 【安安教具】-【数学】-【数轴】模拟器 教你如何用python制作数轴模拟器 python 小项目创作