动态规划的入门理解&例子(LIS、最小编辑距离)

关于动态规划的讲解有很多材料,这里只是按照我自己的理解来表述动态规划。可能并不详细,也不一定完全准确。这里主要通过两个例子LIS和最小编辑距离进一步加深对于动态规划的直观理解。

1. 动态规划入门理解

  • 动态规划方法是把问题向前分解,想要解决一个问题,需要先解决这个问题的子问题,那么要解决子问题,有需要解决子问题的子问题。通过先解决最小的子问题,再不断的解决更上一层的问题,那么就可以解决最终的问题。

  • 欲用动态规划解决问题,首先需要对问题进行定义,利用数学语言描述问题。然后再对问题进行求解,求解的过程中是先求解小问题,再利用小问题的解去求解大问题。这是动态规划中常用的流程。

  • 对问题的定义和求解小问题再求解大问题,其实就是定义状态和解决状态转移。下面就用两个例子(LIS和最小编辑距离)来解释如何定义问题的状态以及推导状态转移公式。

2. LIS(最长递增子序列)

  • LIS问题是求一个长序列的子序列,使的这个子序列是递增的,且是所有递增的子序列中最长的。比如对于序列2 5 4 9 10 6 7 8 11,最长递增子序列有两个,2 5 6 7 8 11和 2 4 6 7 8 11。最长递增子序列问题有时候是只需要知道长度即可,对于前面的序列,最长递增子序列的长度是唯一的,即=6。

  • 当然LIS问题是可以用动态规划的思想来解决的。那么首先思考如何定义问题的状态。最容易想到的定义如下:

d k : 表示序列前k项的最长子序列

  • 对于这个定义,很明显,子问题就是 d k 1 , d k 2 等,分别表示前 k 1 和前 k 2 项的最长子序列。对问题进行定义后,是否合适呢?能否通过该定义推导出状态转移呢?如果对于每一项都求最长的子序列,并且状态转移使用 a k 项和其它的最长子序列相比较的方式,选择是否把 a k 项加入。

  • 对于序列2 5 4 9 10 6 7 8 11

第一项:2
第二项:2 5
第三项:2 5
第四项:2 5 9
第五项:2 5 9 10
第六项:2 5 9 10
第七项:2 5 9 10
….

从这里就可以看出来,该种状态的定义和状态转移的定义是有问题的。6 7 8 这几项不能发挥作用了。

  • 因此这里选择另外一种定义:

d k : 表示以第k项结尾的最长子序列

  • 那么求出所有以1,2,3,4,5…,N项结尾的最长子序列后,选择最长的作为输出即可。那么对于这种状态的定义,状态的转移是什么样子的呢?

h i = { [ d i , a k ] , i f a k > a i a k , o t h e r

d k = h a r g m a x i l e n ( h i )

也就是,求解序列[ a 1 , a 2 , a 3 , …, a k ]的最长递增子序列,可以通过[ a 1 , a 2 , a 3 , … a k 1 ]序列、[ a 1 , a 2 , a 3 , … a k 2 ]、[ a 1 , a 2 ]和[ a 1 ]的最长递增子序列得到。要求长度为k的序列的[ a 1 , a 2 , a 3 , …, a k ]最长递增子序列,需要先求出序列[ a 1 , a 2 , a 3 , …, a k 1 ]中以各元素( a 1 , a 2 , a k 1 )作为最大元素的最长递增序列,然后把所有这些递增序列与 a k 比较,如果序列的末尾元素比 a k 要小,则将元素 a k 加入这个递增子序列,如果序列末尾的元素比 a k 大,则取 a k ,那么现在所有的序列都是以 a k 结尾的,取出序列长度最长的作为以第k项结尾的最长递增子序列。(这里可能会出现两个序列长度一样的情况,那么可以随机选一个,或者是选择第一个)。

  • 对于前面的序列2 5 4 9 10 6 7 8 11,求解顺序如下(存在两个一样长的序列时,选择第一个):

第一项:2
第二项:2 5
第三项:2 4
第四项:2 5 9
第五项: 2 4 9 10
第六项:2 5 6
第七项:2 5 6 7
第八想:2 5 6 7 8
第九项:2 5 6 7 8 11

  • 另外,如果是求子序列,那么是一边计算,也是一边需要保存各项的子序列的。如果是只求子序列的长度,那么只需要保存长度即可。

  • 采用这种方式求解最长递增子序列,时间复杂度为 O ( N 2 ) ,还有更快的,时间复杂度为 O ( N l o g N ) 的算法,这里就不再解释了。

3. 最小编辑距离

  • 最小编辑距离的问题,比较普遍,在平常的编码过程中经常可能会遇到这个问题。最小编辑距离是指把字符串A转换成字符串B所需要的最少操作数,这里的操作包括删除字、增加字、替换字三种操作。
  • 比如小明让小红告诉小刚:“今天天气真好啊”,而小红却告诉小刚:“今天正好呀哈”。 那么就可以用最小编辑距离表示这两句话的区别。这里,增加“天”字,增加“气”字,修改“正”为“真”,修改“呀”为”啊”,删除“哈”字。那么最小编辑距离为5。

  • 要用动态规划的思想解决该问题,同样需要考虑如何定义状态和建立状态转移公式。

首先对问题进行定义:

d i , j : 表示从句子A的前i个字转移到句子B的前j个字的最小编辑距离

状态转移公式如下(假设句子A有N个字符,而句子B有M个字符):

d i , j = { j , i f ( i = 0 , j = 0 , 1 , 2 , 3 , . . . , M ) i , i f ( j = 0 , i = 0 , 1 , 2 , 3 , . . . , N ) max ( d i 1 , j + 1 , d i , j 1 + 1 , d i 1 , j 1 + i s s a m e ) i = 1 , 2 , 3 , . . . , N , j = 1 , 2 , 3 , . . . , M

其中
i s s a m e = { 1 , i f A [ i ] ! = B [ j ] 0 , i f A [ i ] == B [ j ]

更详细的最小编辑距离算法的说明,可以参考博客https://blog.csdn.net/qq_34552886/article/details/72556242

猜你喜欢

转载自blog.csdn.net/b876144622/article/details/80213428
今日推荐