CLRS 15.4最长公共子序列
来源:互联网 发布:如何把mac里的照片导出 编辑:程序博客网 时间:2024/06/05 14:40
15.4-1
对应的LCS为
下面的程序可以验证这个答案
#include <iostream>#include <string>using std::cout;using std::cin;using std::endl;using std::string;void LCS_LENGTH(string &x,string &y,int **b,int **c){ int m = x.size(); int n = y.size(); for(int i = 1; i <= m; i++) c[i][0] = 0; for(int j = 0; j <= n; j++) c[0][j] = 0; for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { if(x[i-1] == y[j-1]) { c[i][j] = c[i-1][j-1] + 1; b[i][j] = 0; } else if(c[i-1][j] >= c[i][j-1]) { c[i][j] = c[i-1][j]; b[i][j] = 1; //up } else { c[i][j] = c[i][j-1]; b[i][j] = 2; //left } } }}void PRINT_LCS(int **b,string &x,int i,int j){ if(i == 0 || j == 0) return; if(b[i][j] == 0) { PRINT_LCS(b,x,i-1,j-1); cout << x[i-1]; } else if(b[i][j] == 1) PRINT_LCS(b,x,i-1,j); else PRINT_LCS(b,x,i,j-1);}int main(){ string x,y; cout << "Enter two strings:"; cin >> x >> y; cout << endl; int m = x.size(),n = y.size(); int **b = new int *[m+1]; int **c = new int *[m+1]; for(int i = 0; i <= m; i++) { b[i] = new int[n+1]; c[i] = new int[n+1]; } LCS_LENGTH(x,y,b,c); PRINT_LCS(b,x,m,n); cout << endl; for(int i = 0; i <= m; i++) { delete []b[i]; delete []c[i]; } delete []b; delete []c; return 0;}
15.4-2
伪代码如下:
PRINT_LCS(c, x, y, i, j) if i = 0 || j = 0 return if x[i] = y[j] PRINT_LCS(c, x, y, i-1, j-1) print x[i] elif c[i-1, j] >= c[i, j-1] PRINT_LCS(c, x, y, i-1, j) else PRINT_LCS(c, x, y, i, j-1)
修改第一题的LCS-LENGTH,PRINT-LCS
,代码如下。
void LCS_LENGTH(string &x,string &y,int **c){ int m = x.size(), n = y.size(); for(int i = 1; i <= m; i++) c[i][0] = 0; for(int j = 0; j <= n; j++) c[0][j] = 0; for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { if(x[i-1] == y[j-1]) c[i][j] = c[i-1][j-1] + 1; else if(c[i-1][j] >= c[i][j-1]) c[i][j] = c[i-1][j]; else c[i][j] = c[i][j-1]; } }}void PRINT_LCS(int **c,string &x,string &y,int i,int j){ if(i == 0 || j == 0) return; if(x[i-1] == y[j-1]) { PRINT_LCS(c,x,y,i-1,j-1); cout << x[i-1]; } else if(c[i-1][j] >= c[i][j-1]) PRINT_LCS(c,x,y,i-1,j); else PRINT_LCS(c,x,y,i,j-1);}
15.4-3
伪代码如下:
LCS-LENGTH(X, Y) m = X.length n = Y.length let c[0..m,0..n]and b[1..m,1..n] be new tables for i = 1 to m for j = 1 to n c[i,j] = -1 LCS-LENGTH-AUX(X,Y,m,n,c,b) return c and bLCS-LENGTH-AUX(X,Y,i,j,c,b) if c[i,j] > -1 return c[i,j] if i = 0 or j = 0 c[i,j] = 0 else if X[i] == Y[j] c[i,j] = LCS-LENGTH-AUX(X,Y,i-1,j-1,c,b) b[i,j] = "↖" elseif LCS-LENGTH-AUX(X,Y,i,j-1,c,b) >= LCS-LENGTH-AUX(X,Y,i-1,j,c,b) c[i,j] = c[i,j-1] b[i,j] = "←" else c[i,j] = c[i-1,j] b[i,j] = "↑" return c[i][j]
可运行代码如下:
int LCS_LEGNTH_AUX(string &x,string &y,int **b,int **c,int i,int j){ if(c[i][j] > -1) return c[i][j]; if(i == 0 || j == 0) c[i][j] = 0; else { if(x[i-1] == y[j-1]) { c[i][j] = LCS_LEGNTH_AUX(x,y,b,c,i-1,j-1) + 1; b[i][j] = 0; } else if(LCS_LEGNTH_AUX(x,y,b,c,i-1,j) >= LCS_LEGNTH_AUX(x,y,b,c,i,j-1)) { c[i][j] = LCS_LEGNTH_AUX(x,y,b,c,i-1,j); b[i][j] = 1; //up } else { c[i][j] = LCS_LEGNTH_AUX(x,y,b,c,i,j-1); b[i][j] = 2; //left } } return c[i][j];}void LCS_LENGTH(string &x,string &y,int **b,int **c){ int m = x.size(), n = y.size(); for(int i = 1; i <= m; i++) for(int j = 1; j <= n; j++) c[i][j] = -1; LCS_LEGNTH_AUX(x,y,b,c,m,n);}
15.4-4
1、使用 2×min(m,n)
表项及
先假设m = X.length,n = Y.length
,并假设
将前一行全部赋值 0,从左到右计算当前行;
当前行计算完之后,将当前行的值赋值给前一行,然后当前行变成下一行(即需要计算的下一个当前行)。
2、使用 min(m,n)
表项及
原理和上面类似,不同的是,我们把
15.4-5
思路就是:得到序列X
排序后的序列Y
,求出X,Y
的 LCS 即可。
15.4-6
用
假设数组 A
为 3,2,8,9,4
,我们用一个同样长度的数组 B
考察这个序列 A
。
首先 A[1]=3
(数组从1开始计数),所以 B[1]=3
,得到序列为3
;
接下来 A[2]=2,B[1]=3>2
,更新B[1]=2
,得到序列为2
;
接着A[3]=8>B[1]=2
,将A[3]
插入到数组B
,即B[2]=8
,得到序列为2,8
;
然后A[4]=9>B[2]=8
,同上使得B[3]=9
;得到序列为2,8,9
;
最后A[5]=4
,小于B[2],B[3]
,更新B[2]=4
,此时序列为2,4,9
。
注意,这个2,4,9并不是我们求出的最后子序列结果,而是表示最长子序列长度为 3,那为什么要在最后一步替换2,8,9为2,4,9呢?明明正确答案就是2,8,9啊!!!因为如果数组 A 为3,2,8,9,4,7,9的话,我们按照上面所说的步骤就会得到2,4,7,9对于长度为 4 的最长单调子序列,而如果不替换则得不到这个结果!
贴一个Leetcode通过的代码
class Solution {public: int lengthOfLIS(vector<int>& nums) { if(nums.empty()) return 0; int n = nums.size(); int *c = new int[n]; int LIS_len = 1; c[0] = nums[0]; for(int i = 1; i < n; i++) { int index = binary_search(c,0,LIS_len - 1,nums[i]); if(index == LIS_len) c[LIS_len++] = nums[i]; else c[index] = nums[i]; } delete []c; return LIS_len; } int binary_search(int *array,int low,int high,int key)//返回第一个大于key的数组下标 { while(low <= high) { int mid = (low + high) / 2; if(array[mid] == key) return mid; else if(array[mid] < key) low = mid + 1; else high = mid - 1; } if(high < 0) return 0; else return high + 1; }};
- CLRS 15.4最长公共子序列
- 《算法导论》CLRS算法C++实现(十二)P208 最长公共子序列LCS
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列...
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- 最长公共子序列
- bzoj 1059: [ZJOI2007]矩阵游戏|二分图匹配|匈牙利算法
- 纯c中char*[]的处理
- CLRS 15.2矩阵链乘法
- CLRS 15.3动态规划原理
- myeclipse中jquery.min.js引入到工程中显示红叉
- CLRS 15.4最长公共子序列
- 【bzoj2697】【特技飞行】【贪心】
- Struts2标签—Iterator标签
- 浅谈JSONP跨域请求
- How to enable virtualization on Thinkpad X1 Carbon with Win10 installed
- 【Java】接口和抽象类的区别
- 黑马程序员---Java基础加强---JDK1.5新特性:注解
- Halcon对象Hobject转换为.net对象Bitmap
- Android中shape的使用