最长公共子序列(LCS)和最长公共子串(LCSubString)
2013-10-05 15:54
441 查看
最长公共子序列 Longest Common Subsequence
问题描述:
给定两个字符串a 和 b, 求两个字符串的最长公共子序列。
分析:
首先,要弄清楚最长公共子序列和最长公共子串的区别,最长公共子序列只要保证元素的顺序不变,中间是可以有间断的,但是最长公用子串要求中间不能有间断。
这个是典型的DP问题,从题目中求最长(最优化)应该可以想到尝试DP。
这个题可以分解为两步,第一步求最长公共子序列的长度,第二步,根据这个长度来构造最长公共子序列。
子问题:
从头数,a中长度为 i, b 中长度为 j 的两子串的最长公共子序列的长度。
状态转移方程:
若a[i] == b[j], 那么 dp[i+1][j+1] = dp[i][j] + 1 ;
若a[i] != b[j], 那么 dp[i+1][j+1] = dp[i+1][j] 或者 dp[i+1][j+1] = dp[i][j+1],两者取最大,所以:
dp[i+1][j+1] = max{ dp[i+1][j] , dp[i][j+1] }
最长公共子串 Longest Common SubString
问题描述:
给定两个字符串a和b,求两个字符串的最长公共子串。
分析:
这个还是动规问题,还是记录最长公共子串的长度。
子问题:
从头开始,a 中到i 和 b 中到 j 的子串的最长公共子串长度.
状态转移方程:
如果 a[i] == b[j], 则 dp[i+1][j+1] = dp[i][j] + 1;
如果a[i] != b[j], 则 dp[i+1][j+1] = 0
为了能输出最长公共子串,用一个max来记录当前最长公共子串的长度,并用list来按顺序记录最长公共子串最后一个字符的下标(记录在其中一个字符串中的小标就可以了)。
package javainterview.string;
import java.util.ArrayList;
public class LCSubString {
public static String[] getLCString(String a, String b){
int aLen = a.length();
int bLen = b.length();
ArrayList<Integer> list = new ArrayList<Integer>();
int max = 0;
int[][] dp = new int[aLen+1][bLen+1];
for(int i=0; i<aLen; i++){
for(int j=0; j<bLen; j++){
if(a.charAt(i) == b.charAt(j)){
dp[i+1][j+1] = dp[i][j] + 1;
}else{
dp[i+1][j+1] = 0;
}
if(dp[i+1][j+1] > max){
max = dp[i+1][j+1];
list.clear();
list.add(j);//键入其中一个就行
}else if(dp[i+1][j+1] == max){
list.add(j);
}
}
}
//构造结果
String[] result = new String[list.size()];
for(int i=0; i<list.size(); i++){
int k = list.get(i);
result[i] = b.substring(k-max+1, k+1);
}
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String a = "ginghaven";
String b = "jingseven";
String[] result = getLCString(a, b);
for(String item : result){
System.out.println(item);
}
}
}
Reference:
http://blog.csdn.net/biangren/article/details/8038605
http://rosettacode.org/wiki/Longest_common_subsequence
问题描述:
给定两个字符串a 和 b, 求两个字符串的最长公共子序列。
分析:
首先,要弄清楚最长公共子序列和最长公共子串的区别,最长公共子序列只要保证元素的顺序不变,中间是可以有间断的,但是最长公用子串要求中间不能有间断。
这个是典型的DP问题,从题目中求最长(最优化)应该可以想到尝试DP。
这个题可以分解为两步,第一步求最长公共子序列的长度,第二步,根据这个长度来构造最长公共子序列。
子问题:
从头数,a中长度为 i, b 中长度为 j 的两子串的最长公共子序列的长度。
状态转移方程:
若a[i] == b[j], 那么 dp[i+1][j+1] = dp[i][j] + 1 ;
若a[i] != b[j], 那么 dp[i+1][j+1] = dp[i+1][j] 或者 dp[i+1][j+1] = dp[i][j+1],两者取最大,所以:
dp[i+1][j+1] = max{ dp[i+1][j] , dp[i][j+1] }
public class LCS{ public static String lcs(String a, String b) { int[][] dp = new int[a.length()+1][b.length()+1]; // row 0 and column 0 are initialized to 0 already for (int i = 0; i < a.length(); i++) for (int j = 0; j < b.length(); j++) if (a.charAt(i) == b.charAt(j)) dp[i+1][j+1] = dp[i][j] + 1; else dp[i+1][j+1] = Math.max(dp[i+1][j], dp[i][j+1]); // read the substring out from the matrix StringBuffer sb = new StringBuffer(); for (int x = a.length(), y = b.length(); x != 0 && y != 0; ) { if (dp[x][y] == dp[x-1][y]) x--; else if (dp[x][y] == dp[x][y-1]) y--; else { // if has equal element at up or left, do not add to the string sb.append(a.charAt(x-1)); x--; y--; } } return sb.reverse().toString(); } public static void main(String[] args) { String str1 = new String("binghaven"); String str2 = new String("jingseven"); System.out.println(lcs(str1,str2)); } }
最长公共子串 Longest Common SubString
问题描述:
给定两个字符串a和b,求两个字符串的最长公共子串。
分析:
这个还是动规问题,还是记录最长公共子串的长度。
子问题:
从头开始,a 中到i 和 b 中到 j 的子串的最长公共子串长度.
状态转移方程:
如果 a[i] == b[j], 则 dp[i+1][j+1] = dp[i][j] + 1;
如果a[i] != b[j], 则 dp[i+1][j+1] = 0
为了能输出最长公共子串,用一个max来记录当前最长公共子串的长度,并用list来按顺序记录最长公共子串最后一个字符的下标(记录在其中一个字符串中的小标就可以了)。
package javainterview.string;
import java.util.ArrayList;
public class LCSubString {
public static String[] getLCString(String a, String b){
int aLen = a.length();
int bLen = b.length();
ArrayList<Integer> list = new ArrayList<Integer>();
int max = 0;
int[][] dp = new int[aLen+1][bLen+1];
for(int i=0; i<aLen; i++){
for(int j=0; j<bLen; j++){
if(a.charAt(i) == b.charAt(j)){
dp[i+1][j+1] = dp[i][j] + 1;
}else{
dp[i+1][j+1] = 0;
}
if(dp[i+1][j+1] > max){
max = dp[i+1][j+1];
list.clear();
list.add(j);//键入其中一个就行
}else if(dp[i+1][j+1] == max){
list.add(j);
}
}
}
//构造结果
String[] result = new String[list.size()];
for(int i=0; i<list.size(); i++){
int k = list.get(i);
result[i] = b.substring(k-max+1, k+1);
}
return result;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String a = "ginghaven";
String b = "jingseven";
String[] result = getLCString(a, b);
for(String item : result){
System.out.println(item);
}
}
}
Reference:
http://blog.csdn.net/biangren/article/details/8038605
http://rosettacode.org/wiki/Longest_common_subsequence
相关文章推荐
- 最长公共子序列与最长公共子串(Longest Common Subsequence, LCS)
- 最长公共子序列(LCS)和最长公共子串(LCS)
- 【算法之动态规划(三)】动态规划算法之:最长公共子序列 & 最长公共子串(LCS),字符串相似度算法
- 《算法导论》读书笔记之动态规划—最长公共子序列 & 最长公共子串(LCS)
- LCS(最长公共子序列) GST(最长公共子串,广义后缀树)
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 常考的经典算法--最长公共子序列(LCS)与最长公共子串(DP)
- 面试(动态规划算法之:最长公共子序列 & 最长公共子串(LCS))
- 动态规划 最长公共子序列LCS、最长公共连续子串、最长重复子串
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- LCS(最长公共子序列)注意:是可以不连续的,区别于最长公共子串
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 最长公共子序列(LCS)和最长公共连续子串
- 动态划归:最长公共子串和最长公共子序列--LCS
- 动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 算法12—动态规划算法之:最长公共子序列 & 最长公共子串(LCS)
- 动态规划 最长公共子序列 LCS,最长单独递增子序列,最长公共子串
- LCS问题及拓展:最长公共子序列和最长公共子串
- 转【算法之动态规划(三)】动态规划算法之:最长公共子序列 & 最长公共子串(LCS)&字符串相似度算法
- 最长公共子串和最长公共子序列(LCS)