LCS最大公共子序列问题
在生物应用中,经常需要比较两个(或多个)不同生物体的DNA,
例如:某种生物的DNA可能为S1=ACCGGTCGAGTGCGCGGAAGCCGGCCGAA,
另一种生物的DNA可能为S2=GTCGTTCGGAATGCCGTTGCTCTGTAAA
我们比较两个DNA串的一个原因是希望确定它们的相似度,作为度量两种生物的近似程度指标
寻找第三个串S3,它所有碱基也都出现在S1和S2中,且三个串中的顺序都相同,但在S1和S2中不要求连续出现。
可以找到的S3越长,就可以认为S1和S2的相似度越高。在这个例子中最长的S3为GTCGTCGGAAGCCGGCCGAA
我们定义C[i, j]表示Xi和Yj的LCS长度。如果i = 0或j = 0,即一个序列长度为0,那么LCS的长度为0
根据LCS问题的最优子结构性质,可得如下公式:
C[i, j] = 0,若i = 0 或 j = 0
C[i, j] = C[i - 1, j - 1] + 1,若i,j > 0 且 Xi = Yj
C[i, j] = max(C[i, j - 1], C[i - 1, j]) ,若i, j > 0且Xi != Yj
代码如下:
package 动态规划; /**
* Lcs即最长公共子序列问题(longest common subsequence problem)
* @author wangdong20
*
*/
public class Lcs {
public static final int empty = 0;
public static final int upLeft = 1;
public static final int up = 2;
public static final int left = 3; public static int[][][] lcsLength(String x, String y){
int m = x.length();
int n = y.length();
int[][][] result = new int[2][m + 1][n + 1]; // result[0]表示子序列长度 result[1]表示LCS矩阵方向 for(int i = 0; i < m + 1; i++){
result[0][i][0] = 0;
result[1][i][0] = empty;
} for(int j = 0; j < n + 1; j++){
result[0][0][j] = 0;
result[1][0][j] = empty;
} for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(x.charAt(i - 1) == y.charAt(j - 1)){
result[0][i][j] = result[0][i - 1][j - 1] + 1;
result[1][i][j] = upLeft;
}
else if(result[0][i - 1][j] >= result[0][i][j - 1]){
result[0][i][j] = result[0][i - 1][j];
result[1][i][j] = up;
}
else{
result[0][i][j] = result[0][i][j - 1];
result[1][i][j] = left;
}
}
} return result;
} public static void printLcs(int[][][] b, String x, int i, int j){
if(i == 0 || j == 0)
return;
if(b[1][i][j] == upLeft){
printLcs(b, x, i - 1, j - 1);
System.out.print(x.charAt(i - 1));
}
else if(b[1][i][j] == up){
printLcs(b, x, i - 1, j);
}
else{
printLcs(b, x, i, j - 1);
}
} /**
* @param args
*/
public static void main(String[] args) {
// TODO 自动生成方法存根
String s1 = "ACCGGTCGAGTGCGCGGAAGCCGGCCGAA";
String s2 = "GTCGTTCGGAATGCCGTTGCTCTGTAAA";
String s3 = "amputation";
String s4 = "spanking"; System.out.println("s1: " + s1);
System.out.println("s2: " + s2);
System.out.println("最长公共子序列: "); int result[][][] = lcsLength(s1, s2);
printLcs(result, s1, s1.length(), s2.length()); System.out.println("\ns3: " + s3);
System.out.println("s4: " + s4);
System.out.println("最长公共子序列: "); int result2[][][] = lcsLength(s3, s4);
printLcs(result2, s3, s3.length(), s4.length());
} }
实质上lcsLength(s3, s4)返回的是两个二维数组组成的三维数组
代码中result[0][i][j]保存的是图中显示的到字符串Xi, Yj目前的LCS长度
result[1][i][j]保存的是图中显示的字符串Xi, Yj的指引方向关系
得到这幅图我们就可以从中得出表b[m, n]
为了得出最后的LCS字符串,只需要从b[m, n]开始,按照箭头方向追踪下去即可。
当b[i, j]遇到upLeft左上时,意味着Xi = Yj是LCS的一个元素.
按照这种方法可以逆序依次构造出LCS的所有元素
public static void printLcs(int[][][] b, String x, int i, int j){
if(i == 0 || j == 0)
return;
if(b[1][i][j] == upLeft){
printLcs(b, x, i - 1, j - 1);
System.out.print(x.charAt(i - 1));
}
else if(b[1][i][j] == up){
printLcs(b, x, i - 1, j);
}
else{
printLcs(b, x, i, j - 1);
}
}
最后运行结果:
LCS最大公共子序列问题的更多相关文章
- python3 lcs 最大公共子序列
抛出问题: 假定字符串 s1 = 'BDCABA', s2 = 'ABCBDAB',求s1和s2的最大公共子序列. 问题分析: 我们想要求出s1和s2的最大公共子序列,我们可以用c(i,j)表示s1( ...
- LCS最大公共子序列【转载】
在两个字符串中,有些字符会一样,可以形成的子序列也有可能相等,因此,长度最长的相等子序列便是两者间的最长公共字序列,其长度可以使用动态规划来求. 以s1={1,3,4,5,6,7,7,8},s2={3 ...
- 动态规划之LCS(最大公共子序列)
#include <stdio.h> #include <string.h> int b[50][50]; int c[50][50]; int length = 0; voi ...
- Poj1159 Palindrome(动态规划DP求最大公共子序列LCS)
一.Description A palindrome is a symmetrical string, that is, a string read identically from left to ...
- Advanced Fruits (最大公共子序列的路径打印)
The company "21st Century Fruits" has specialized in creating new sorts of fruits by trans ...
- hdu 1243 反恐训练营(dp 最大公共子序列变形)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=1243 d[i][j] 代表第i 个字符与第 j 个字符的最大的得分.,, 最大公共子序列变形 #inclu ...
- spoj Longest Common Substring (多串求最大公共子序列)
题目链接: https://vjudge.net/problem/SPOJ-LCS 题意: 最多10行字符串 求最大公共子序列 数据范围: $1\leq |S| \leq100000$ 分析: 让他们 ...
- POJ - 2250 Compromise (LCS打印序列)
题意:给你两个单词序列,求出他们的最长公共子序列. 多组数据输入,单词序列长度<=100,单词长度<=30 因为所有组成LCS的单词都是通过 a[i] == b[j] 更新的. 打印序列的 ...
- Common Subsequence 最大公共子序列问题
Problem Description A subsequence of a given sequence is the given sequence with some elements (poss ...
随机推荐
- 蛋疼的Apple IOS Push通知协议
简单介绍 Apple Push通知机制事实上非常easy,就是Apple的APNsserver做为中间人,把消息推送到相应的设备上. 一张来自Apple文档的图: 当然,示意图看起来简单,可是另一些实 ...
- tab group of firefox
https://addons.mozilla.org/en-US/firefox/addon/tabgroups-menu/? src=search#detail-relnotes https://g ...
- codeforces #267 C George and Job(DP)
职务地址:http://codeforces.com/contest/467/problem/C 太弱了..这题当时都没做出来..思路是有的,可是自己出的几组数组总是过不去..今天又又一次写了一遍.才 ...
- jQuery 删除HTML元�
jQuery使用以下两个方法来删除或是清空某个HTML元素. remove() – 删除指定的元素(包含其子元素) empty() – 清空指定元素的子元素 比如: <!DOCTYPE html ...
- Java基础06 组合
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们已经尝试去定义类.定义类,就是新建了一种类型(type).有了类,我们接着构造 ...
- 基于visual Studio2013解决C语言竞赛题之1026判断排序
题目 解决代码及点评 /********************************************************************** ...
- UPC 2959: Caoshen like math 这就是个水题
http://acm.upc.edu.cn/problem.php?id=2959 这就是个水题,之所以要写这个题是感觉很有纪念意义 用力看就是盲……23333333333333333 这个题就是最小 ...
- 页面提交进不了Action的原因
1.进不了action,页面没有任何js报错,可能的原因是数据类型不一致.例如用ajax方式提交所带的参数类型a是String类型,而action中定义的a是Integer类型就会导致这种情况的发生.
- JVM类加载过程学习总结
JVM类加载过程学习总结 先不说JVM类加载的原理,先看实例: NormalTest类,包含了一个静态代码块,执行的任务就是打印一句话. /** * 在正常类加载条件下,看静态代码块是否会执行 * @ ...
- 《C陷阱与缺陷》整理二
1.数组名作实參 在C语言中,我们没有办法将一个数组作为函数參数传递,假设我们使用数组名作为參数.这个时候数组名立马会被转换为指向该数组的第一个元素的指针. 关于这一点的理解能够向前深 ...