您的位置:首页 > 其它

最长公共子序列(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] }

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐