在生物应用中,经常需要比较两个(或多个)不同生物体的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最大公共子序列问题的更多相关文章

  1. python3 lcs 最大公共子序列

    抛出问题: 假定字符串 s1 = 'BDCABA', s2 = 'ABCBDAB',求s1和s2的最大公共子序列. 问题分析: 我们想要求出s1和s2的最大公共子序列,我们可以用c(i,j)表示s1( ...

  2. LCS最大公共子序列【转载】

    在两个字符串中,有些字符会一样,可以形成的子序列也有可能相等,因此,长度最长的相等子序列便是两者间的最长公共字序列,其长度可以使用动态规划来求. 以s1={1,3,4,5,6,7,7,8},s2={3 ...

  3. 动态规划之LCS(最大公共子序列)

    #include <stdio.h> #include <string.h> int b[50][50]; int c[50][50]; int length = 0; voi ...

  4. Poj1159 Palindrome(动态规划DP求最大公共子序列LCS)

    一.Description A palindrome is a symmetrical string, that is, a string read identically from left to ...

  5. Advanced Fruits (最大公共子序列的路径打印)

    The company "21st Century Fruits" has specialized in creating new sorts of fruits by trans ...

  6. hdu 1243 反恐训练营(dp 最大公共子序列变形)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1243 d[i][j] 代表第i 个字符与第 j 个字符的最大的得分.,, 最大公共子序列变形 #inclu ...

  7. spoj Longest Common Substring (多串求最大公共子序列)

    题目链接: https://vjudge.net/problem/SPOJ-LCS 题意: 最多10行字符串 求最大公共子序列 数据范围: $1\leq |S| \leq100000$ 分析: 让他们 ...

  8. POJ - 2250 Compromise (LCS打印序列)

    题意:给你两个单词序列,求出他们的最长公共子序列. 多组数据输入,单词序列长度<=100,单词长度<=30 因为所有组成LCS的单词都是通过 a[i] == b[j] 更新的. 打印序列的 ...

  9. Common Subsequence 最大公共子序列问题

    Problem Description A subsequence of a given sequence is the given sequence with some elements (poss ...

随机推荐

  1. JavaScript实现获取table中某一列的值

    JavaScript实现获取table中某一列的值 1.实现源代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional/ ...

  2. qingshow “不积跬步无以至千里,不积小流无以成江海”。--荀子《劝学篇》 用tomcat+花生壳搭建自己的web服务器+域名(参考)

    链接地址:http://www.blogjava.net/qingshow/archive/2010/01/17/309846.html 用tomcat搭建web服务器 目标:免费拥有自己的网站及域名 ...

  3. 分布式消息系统jafka快速起步(转)

    Jafka 是一个开源的/性能良好的分布式消息系统.在上一篇文章中有所简单介绍.下面是一篇简单的入门文档.更多详细的文档参考wiki. Step 1: 下载最新的安装包 完整的安装指南在这里.最新的发 ...

  4. HTML+CSS - 前端设计的小技巧(持续更新......)

    2015年7月6日20:28:20 1.设置文字的居中,非控件内的. :text-alain:center 2.图片在ASP.NET中,可以直接拖放到界面,自动形成img控件. 3.CSS直接在全局样 ...

  5. python for else

    http://blog.sina.com.cn/s/blog_5357c0af01013mwn.html raw_input() 与 input() __ Python http://www.cnbl ...

  6. Delphi + Asm - TBits类的学习

    技术交流,DH讲解. 在D2010的classes中有个TBits类,这个类主要是位操作的. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 TBits = class privat ...

  7. OpenCV中遇到Microsoft C++ 异常 cv::Exception

    我在实现<OpenCV2计算机视觉编程手册>第2章 2.2 节 存取像素值 中的椒盐噪声例子中遇到的程序错误. 原始输入程序: #include <opencv2/core/core ...

  8. spring mvc controller json数据

    项目中遇到个批处理,需要前台传递一个json格式对象数组,如下:var data={   "wos":[{"id":1,"satisfaction&q ...

  9. (step6.3.3)hdu 1150(Machine Schedule——二分图的最小点覆盖数)

    题目大意:第一行输入3个整数n,m,k.分别表示女生数(A机器数),男生数(B机器数),以及它们之间可能的组合(任务数). 在接下来的k行中,每行有3个整数c,a,b.表示任务c可以有机器A的a状态或 ...

  10. alv 显示 汇总数据

    alv中有 字段设置 gs_fieldcat-do_sum = ‘1’.字段  用于控制汇总