LIS和LCS
2016-10-23 16:43
260 查看
最长上升子序列
参考博文:http://blog.csdn.net/chenwenshi/article/details/6027086问题描述
对给定的序列,求最长上升子序列的长度。(子序列不需要连续)
例如(1,7,3,5,9,4,8),那么它的最长子序列为(1,3,5,9),其实还有其它子序列是最长的,但这里只要求长度即可,不深究(但要实现输出所有的最长子序列也不难,利用递归即可)。
解决思路
序列为num[],对于序列的位置k,它的LIS长度就是0~k-1位置中num值小于num[k]且LIS长度最大的那个值+1。
代码
int LIS(vector<int>& nums) { vector<int> maxLen; maxLen.resize(nums.size()); maxLen[0]=1; int result = 1; for(int i=1; i<nums.size(); ++i) { int tmp=0; for(int j=0; j<i; ++j) if(nums[j]<nums[i] && tmp<maxLen[j]) tmp = maxLen[j]; maxLen[i] = tmp+1; if(result < maxLen[i]) result = maxLen[i]; } return result; }
最长公共子序列
参考博文:http://blog.csdn.net/yysdsyl/article/details/4226630问题描述
两个字符序列的最长公共字符子序列,序列不需要连续。会看这个,应该知道什么是最长公共子序列,不作详述。
解决思路
假设字符串str1[]和str2[](假设下标从1开始),
用2个整型数组存储DP过程,
c[i][j]表示str1[i]和str2[j]的LCS,
b[i][j]表示c[i][j]是通过哪个方向求得的,0表示c[i][j]=c[i-1][j-1]+1,-1表示c[i][j] = c[i][j-1],1表示c[i][j] = c[i-1][j],通过b[i][j]可以确定搜索方向。
对于”BDCABA”和”ABCBDAB”,c[i][j]如下:
代码
//代码量其实不多,只是内存申请和初始化的代码比较多 string LCS(string& str1,string& str2) { string result; if(str1.length()==0 || str1.length()==0) return result; int len1 = str1.length(); int len2 = str2.length(); int **c = new int*[len1+1]; for(int i=0; i<=len1; ++i) c[i] = new int[len2+1]; int **b = new int*[len1+1]; for(int i=0; i<=len1; ++i) b[i] = new int[len2+1]; for(int i=0;i<=len1; ++i) c[i][0] = 0; for(int i=0;i<=len2; ++i) c[0][i] = 0; for(int i=1; i<=len1; ++i) { for(int j=1; j<=len2; ++j) { if(str1[i-1] == str2[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; } else { c[i][j] = c[i][j-1]; b[i][j] = -1; } } } int i=len1, j=len2; while(i>0&&j>0) { if(b[i][j]==0) { result.push_back(str1[i-1]); --i;--j; } else if(b[i][j]==1) --i; else --j; } for(int i=0; i<result.length()/2; ++i) swap(result[i], result[result.length()-1-i]); for(int i=0; i<=len1; ++i) delete[] c[i]; delete[] c; for(int i=0; i<=len1; ++i) delete[] b[i]; delete[] b; return result; }
最长公共子串
参考博文:http://www.cnblogs.com/ider/p/longest-common-substring-problem-optimization.html最长公共子串和最长公共子序列简称都是LCS,前者是Longest Common Substring,后者是Longest Common Subsequent。
问题描述
两个字符串的最长公共字符子串,串是连续。
解决思路
跟最长公共子序列的问题相似,但因为子串连续的特性,所以最长公共子串求解过程中的临时解数组只与左上角的值相关。
所以,如果我们只需要求解一个满足条件的解,可以将二维数组的空间减少到2个一维数组的空间。说不清。。见代码吧。。
当然,如果要输出所有的解,那么还是需要二维数组的空间的。
代码
string LCSstr(const string& str1, const string& str2) { string ret; if(str1.length()==0 || str2.length()==0) return ret; int len1 = str1.length(); int len2 = str2.length(); vector<vector<int> > table(2, vector<int>(len2 a20c , 0)); int maxLen = 0; int maxi = -1; for(int j=0; j<len2; ++j) { table[0][j] = str1[0]==str2[j]?1:0; if(maxLen<table[0][j]) { maxLen = table[0][j]; maxi = 0; } } for(int i=1; i<len1; ++i) { int cur = i&1; table[cur][0] = str1[i]==str2[0]?1:0; if(maxLen<table[cur][0]) { maxLen = table[cur][0]; maxi = i; } for(int j=1; j<len2; ++j) { table[cur][j] = str1[i]==str2[j]?table[!cur][j-1]+1:0; if(maxLen<table[cur][j]) { maxLen = table[cur][j]; maxi = i; } } } int si = maxi - maxLen + 1; for(int i=0; i<maxLen; ++i) ret.push_back(str1[si+i]); return ret; }
相关文章推荐
- 编号(长度)为状态的动态规划(LCS,LIS等)
- 动态规划--LIS与LCS
- LCS问题与LIS问题--Java语言
- LCS LIS
- uva 10635 - Prince and Princess lcs->lis 2018-2-8
- LCS转LIS(大地的秘密题解)
- LCS/LIS/LCIS
- UVa 10635 Prince and Princess / LCS 转 LIS
- NYOJ 题目760 See LCS again(LIS求LCS)
- 动态规划总结之 LIS ,LCS
- uva10635 LCS映射转LIS
- 【动态规划14】UVA10635 Prince and princess(LCS转LIS)
- LIS&&LCS
- LCS时间复杂度O(NlogN) (LCS 转 LIS)
- UVA 10635 - Prince and Princess (LCS转成LIS DP)
- 动态规划 LCS,LIS
- 最长公共子序列(LCS)、最长递增子序列(LIS)、最长递增公共子序列(LICS)
- LCS?LIS
- 动态规划面试题基础合集1--数学三角形,LIS , LCS, CSD
- (UVA - 10635)Prince and Princess (LCS变形为LIS,DP)