与动态规划算法MATRIX_CHAIN_ORDER一样,备忘录算法MEMOIZED_ MATRIX_CHAIN用数组m[1…n,1…n]的单元m[i,j]来记录解子问题Ai…j的最优计算量。M[i,j]初始化为∞,表示相应于Ai…j的子问题还未被计算。在调用LOODKUP _CHAIN(P,i,j)时,若m[i,j]<∞,则表示m[i,j]中存储的是所要求子问题的计算结果,直接返回此结果即可。否则与直接递归算法一样,自顶向下地递归计算,并将计算结果存入m[i,j]后返回。因此,LOODKUP_CHAIN(P,i,j)总能正确返回m[i,j]的值,但仅在它第一次被调用时计算,以后的调用就直接返回计算结果。
一般地讲,当一个问题的所有子问题都至少要解一次时,用动态规划算法解比用备忘录方法好。此时,动态规划算法没有任何多余的计算。同时,对于许多问题,常可利用其规则的表格存取方式,来减少在动态规划算法中的计算时间和空间需求。当子问题空间中的部分子问题可不必求解时,用备忘录方法则较有利,因为从其控制结构可以看出,该方法只解那些确实需要求解的子问题。
例3 最长公共子序列问题LCS
问题描述 一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说,若给定序列X=<x1, x2,…, xm>,则另一序列Z=<z1, z2,…, zk>是X的子序列是指存在一个严格递增的下标序列 <i1, i2,…, ik>,使得对于所有j=1,2,…,k有
例如,序列Z=是序列X=的子序列,相应的递增下标序列为<2,3,5,7>。
给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。例如,若X=和Y=,则序列是X和Y的一个公共子序列,序列也是X和Y的一个公共子序列。而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。
最长公共子序列(LCS)问题:给定两个序列X=<x1, x2, …, xm>和Y=<y1, y2, … , yn>,要求找出X和Y的一个最长公共子序列。
参考解答 动态规划算法可有效地解此问题。下面我们按照动态规划算法设计的各个步骤来设计一个解此问题的有效算法。
1.最长公共子序列的结构
解最长公共子序列问题时最容易想到的算法是穷举搜索法,即对X的每一个子序列,检查它是否也是Y的子序列,从而确定它是否为X和Y的公共子序列,并且在检查过程中选出最长的公共子序列。X的所有子序列都检查过后即可求出X和Y的最长公共子序列。X的一个子序列相应于下标序列{1, 2, …, m}的一个子序列,因此,X共有2m个不同子序列,从而穷举搜索法需要指数时间。
事实上,最长公共子序列问题也有最优子结构性质,因为我们有如下定理:
设序列X=1, x2, …, xm>和Y=1, y2, …, yn>的一个最长公共子序列Z=1, z2, …, zk>,则:
若xm=yn,则zk=xm=yn且Zk-1是Xm-1和Yn-1的最长公共子序列;
若xm≠yn且zk≠xm ,则Z是Xm-1和Y的最长公共子序列;
若xm≠yn且zk≠yn ,则Z是X和Yn-1的最长公共子序列。
其中Xm-1=1, x2, …, xm-1>,Yn-1=1, y2, …, yn-1>,Zk-1=1, z2, …, zk-1>。
证明 用反证法。若zk≠xm,则1, z2, …, zk ,xm >是X和Y的长度为k十1的公共子序列。这与Z是X和Y的一个最长公共子序列矛盾。因此,必有zk=xm=yn。由此可知Zk-1是Xm-1和Yn-1的一个长度为k-1的公共子序列。若Xm-1和Yn-1有一个长度大于k-1的公共子序列W,则将xm加在其尾部将产生X和Y的一个长度大于k的公共子序列。此为矛盾。故Zk-1是Xm-1和Yn-1的一个最长公共子序列。
由于zk≠xm,Z是Xm-1和Y的一个公共子序列。若Xm-1和Y有一个长度大于k的公共子序列W,则W也是X和Y的一个长度大于k的公共子序列。这与Z是X和Y的一个最长公共子序列矛盾。由此即知Z是Xm-1和Y的一个最长公共子序列。
与 2.类似。
这个定理告诉我们,两个序列的最长公共子序列包含了这两个序列的前缀的最长公共子序列。因此,最长公共子序列问题具有
最优子结构性质。
2.子问题的递归结构
由最长公共子序列问题的最优子结构性质可知,要找出X=1, x2, …, xm>和Y=1, y2, …, yn>的最长公共子序列,可按以下方式递归地进行:当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。当xm≠yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。这两个公共子序列中较长者即为X和Y的一个最长公共子序列。
由此递归结构容易看到最长公共子序列问题具有
子问题重叠性质。例如,在计算X和Y的最长公共子序列时,可能要计算出X和Y
n-1及X
m-1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算X
m-1和Y
n-1的最长公共子序列。
与矩阵连乘积最优计算次序问题类似,我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi