动态规划——最长公共子序列

动态规划——最长公共子序列_第1张图片

 按照递增的下标,找出序列X和序列Y的最长公共子序列,子序列元素在原序列中可以不连续。比如题中给出的例子中,XY的最长公共子序列可以是BCBA,BCAB也可以是BDAB,它们的长度都是4。

动态规划——最长公共子序列_第2张图片

动态规划——最长公共子序列_第3张图片 

 想起动态规划的要求,我们需要保存曾经计算过的结果,避免重复运算,因此设置一个二维数组C[i][j],分别表示X的长度为i和Y的长度为j时二者的最大公共子序列长度。

我们使用动态规划的方法,最长子序列一定是由最小的那个序列的长度决定的,因此我们的遍历寻找次数应当基于最短的序列长度。比如X总共8位,Y总共5位,那么当j=5,j再增长也没有意义了,比如C[6][6]=C[6][5],不可能比C[5][5](即C[5][6],二者同样)要更小,因此C[6][6]=max{C[6][5],C[5][6]},C[i+1][j+1]=max{C[i+1][j],C[i][j+1]}化为C[i][j]=max{C[i][j-1],C[i-1][j]}

假设我们已经找到了X(n-1)和Y(m-1)的最长公共子序列Z,若在X和Y后面都添加一个元素,如果添加的元素Xn和Ym相同,那么我们下子序列就要增加一位,即Xi=Yi时,C[i][j]=C[i-1][j-1]+1

反之如果不相同子序列也不一定不增加,因为可能产生新的更长的子序列,比如X新加一位后,原来的Y中正好有更长的子序列符合新的X,或者反之Y增加一位X中有更长的子序列。即Xi !=Yi,C[i+1][j+1]=max{C[i+1][j],C[i][j+1]}化为C[i][j]=max{C[i][j-1],C[i-1][j]}

动态规划——最长公共子序列_第4张图片

动态规划——最长公共子序列_第5张图片 

这里的数组b用于记录C[i][j]经历了哪种操作

b[i][j]=1——C[i][j]=C[i-1][j-1]+1

b[i][j]=2——C[i][j]=C[i-1][j]

b[i][j]=3——C[i][j]=C[i][j-1]

动态规划——最长公共子序列_第6张图片

最后按照b数组每次递归输出x数组(因为是公共子序列,选择X还是Y输出是无所谓的)中的第i个字符,由于顺序是由大到小的,所以从递归最内层开始输入逐渐到外层,就是x中的最长公共子序列的输出结果。

 

你可能感兴趣的:(算法设计与分析例题分析,动态规划,算法)