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

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

 

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

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

求最长公共子序列(LCS)

问题描述:

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

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

问题分析:

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

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

设X=x1x2...xm和Y=y1y2...yn是两个序列,Z=z1z2...zk是X和Y的一个最长公共子序列。

(1)如果xm=yn,那么zk=xm=yn,且Zk−1是Xm−1和Yn−1的一个最长公共子序列。

(2)如果xm≠yn,那么zk≠xm,蕴含着Z是Xm−1和Y的一个最长公共子序列。

(3)如果xm≠yn,那么zk≠yn,蕴含着Z是X和Yn−1的一个最长公共子序列。

2) 递归定义最优解的值

l[i,j]={0,i=0或j=0l[i−1,j−1],i,j>0且xi=yjmax(l[i−1,j],l[i,j−1]),i,j>0且xi≠yj

3) 代码演示

C++

Python

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