动态规划—最长公共子序列LCS
来源:互联网 发布:linux iso文件怎么挂载 编辑:程序博客网 时间:2024/05/24 04:50
最长公共子序列问题可以描述如下:
给定两个序列X[0,····m]和Y[0,····n],找出X和Y的最大长度的公共子序列S,即最长公共子序列问题(longest common sequence )。
分析:
假设Z[0,····k]是X和Y的一个LCS,那么存在如下规律:
1. 如果X[m] == Y[n] == Z[k], 那么Z[0,···k-1]为 X[0···m-1]和Y[0····n-1]的一个LCS。
2.如果X[m] != Y[n], 那么Z[k] != X[m] 意味着Z[0···k]为X[0···m-1]和Y[0····n]的一个LCS。
3.如果X[m] != Y[n], 那么Z[k] != Y[n] 意味着Z[0···k]为X[0···m]和Y[0····n-1]的一个LCS。
从以上三条就可以看出最长公共子序列具有最优子结构(即一个问题的最优解包含了子问题的最优解)。而最优子结构也是动态规划的一个基本要素。
根据上面的三条规律,可以知道如果要求得X = ( x1,x2,···,xm)和Y = ( y1,y2,···,yn)的一个LCS,那么就要考虑下面两种情况:
1.如果xm == yn,那么接下来就要求Xm-1和Yn-1的一个LCS,将Xm加上去就构成了X和Y的一个LCS。
2.如果xm != yn,那么就要求得Xm-1和Y的一个LCS,以及Xm和Yn-1的一个LCS,二者中较长的即X和Y的一个LCS。
从这里也可以看到该问题的重叠子问题性质(不同的子问题包含共同的子子问题),这也是动态规划的第二个要素。
通过上面的分析,可以确定LCS可以通过动态规划进行求解。
由LCS的最优子结构可以得到如下递归方程:
0 如果 i = 0 或 j = 0
C[i,j] = c[i-1,j-1] 如果i,j>0, xi == yj
Max(c[i-1,j], c[i, j-1]) 如果 i,j > 0 ,xi != yj
根据上面的递归方程,可以写出函数来计算LCS的长度。为了求出LCS,可以维护一个辅助的二维数组action,并定义一个枚举类型enum Action {both_erase, x_erase, y_erase }。
过程如下:
void lcs( char seq1[], char seq2[], int len[][length2+1], Action action[][length2], int len1, int len2 ){int i, j;for( i = 0; i <= length1; ++i )len[i][0] = 0;for( j = 0; j <= length2; ++j )len[0][j] = 0;for( i = 0; i < length1; ++i )for( j = 0; j < length2; ++j ){if( seq1[i] == seq2[j] ){len[i+1][j+1] = len[i][j] + 1;action[i][j] = both_erase;}else{len[i+1][j+1] = len[i+1][j] >= len[i][j+1] ? len[i+1][j] : len[i][j+1];if( len[i+1][j+1] == len[i][j+1] ).action[i][j] = x_erase;elseaction[i][j] = y_erase;}}}
len[i][j]表示seq1[0···i-1]和seq2[0···j-1]两个序列之间的lcs的长度,action[i][j] 表示在输出seq1[0···i]和seq2[0···j]两个序列的lcs时应该采取的动作,以便后面可以根据action打印出LCS。
打印函数如下:
void print( char seq1[], Action action[][length2], int len1, int i, int j ){if( i >= 0 && j >= 0 ){if( action[i][j] == both_erase ){print( seq1, action, len1, i-1, j-1 );cout << seq1[i];}else if( action[i][j] == x_erase )print( seq1, action, len1, i-1, j );elseprint( seq1, action, len1, i, j-1 );}}
不需要辅助数组action的打印函数如下:
void print_without_ancillary_space( char seq1[], int len[][length2+1], int i , int j ){if( i > 0 && j > 0 ){if( len[i][j] == len[i-1][j] ){print_without_ancillary_space( seq1, len, i-1, j );}else if ( len[i][j] == len[i][j-1] ){print_without_ancillary_space( seq1, len, i, j-1 );}else if( len[i][j] == len[i-1][j-1] + 1 ){print_without_ancillary_space( seq1, len, i-1, j-1 );cout << seq1[i-1];}}}
- 【动态规划】最长公共子序列LCS
- 动态规划---LCS最长公共子序列
- 动态规划-最长公共子序列【LCS】
- 动态规划-最长公共子序列(LCS)
- 动态规划-LCS最长公共子序列
- 动态规划----最长公共子序列LCS
- (动态规划)LCS-最长公共子序列
- 动态规划 最长公共子序列LCS
- 动态规划——最长公共子序列(LCS)
- 动态规划——最长公共子序列(LCS)
- 动态规划——最长公共子序列问题(LCS)
- 动态规划——最长公共子序列LCS
- 动态规划—最长公共子序列LCS
- 动态规划——最长公共子序列(LCS)&最长递增子序列(LIS)
- 动态规划 最长公共子序列LCS、最长公共连续子串、最长重复子串
- 动态规划实现最长公共子序列(LCS)算法
- 动态规划之最长公共子序列(lcs)
- 动态规划之最长公共子序列(lcs)
- VBS脚本控制软件网络代理启用与否--IE,Firefox,有道词典
- sql server行列转化和行列置换
- HCI Design:3 Phrases
- 精简ubuntu 虚拟机 缩小 磁盘
- hibernate数据类型,标准sql数据类型之间的对应表
- 动态规划—最长公共子序列LCS
- expdp-impdp问题及处理过程(ORA-00832,ORA-01552)
- UI Design Framework-Case Study of SG
- Unix Network Programming
- POJ3784Running Median——双向链表/堆
- sequence更新
- matlab图像处理为什么要归一化和如何归一化
- 超级烂片《盗梦空间》
- MySQL5.5 RPM安装的默认安装路径