算法基础:动态规划(二)

算法基础:动态规划(二)

 

算法基础:动态规划(二)

关于动态规划,这里再举一个书上的经典例子。

求最长公共子序列(LCS)

问题描述:

令序列X=x1x2x3...xm ,序列 Y=y1y2...ykX 的子序列,存在X 的一个严格递增下标序列<i1,i2,...,ik>,使得对于所有的j=1,2,...,kxij=yj。例如,X=ABCBDAB,Y=BCDB,则YX的一个子序列。

给定两个序列XY,称序列ZXY的公共子序列,是指Z同时是XY的组序列。最长公共子序列问题定义为:给定序列X=x1x2...xmY=y1y2...yn,求这两个序列的最长公共子序列 。以X=ABCBDAB,Y=BCDB为例,两者的公共子序列为Z=BCDB

问题分析:

如果是匹配字符串问题的话,可以用经典KMP算法,可惜不是,求不得。如果使用暴力算法,穷举X的所有子序列,并与Y序列比较,其时间复杂度可以达到O(2mn),对于长序列来说,这个代价是不可接受的。那我们使用动态规划按照以下步骤来解决这个问题:

1)刻画最长公共子序列问题的最优子结构。

X=x1x2...xmY=y1y2...yn是两个序列,Z=z1z2...zkXY的一个最长公共子序列。

(1)如果xm=yn,那么zk=xm=yn,且Zk1Xm1Yn1的一个最长公共子序列。

(2)如果xmyn,那么zkxm,蕴含着ZXm1Y的一个最长公共子序列。

(3)如果xmyn,那么zkyn,蕴含着ZXYn1的一个最长公共子序列。

2) 递归定义最优解的值

l[i,j]={0,i=0j=0l[i1,j1],i,j>0xi=yjmax(l[i1,j],l[i,j1]),i,j>0xiyj

3) 代码演示

C++

Python

这么看来动态规划算法的有两个比较难的点:写出最优解结构的递归式和找到合适的回溯算法。