Java实现最长公共子序列(LCS)算法:动态规划解法
Java实现最长公共子序列(LCS)算法:动态规划解法
在生物信息学中,经常需要比较两个或多个DNA序列的相似程度。DNA是由碱基分子组成的串,这些碱基是腺嘌呤(adenine)、鸟嘌呤(guanine)、胞嘧啶(cytosine)和胸腺嘧啶(thymine),通常用它们对应英文单词的第一个字母表示,分别为A、G、C和T。例如,一种组织的DNA序列为S1='ACCGGTCGAGTGCGCGGAAGCCGGCCGAA',而另一种组织的序列为S2='GTCGTTCGGAATGCCGTTGCTCTGTAAA'。
度量相似性常用的方法之一是:如果存在串S3,且S3中的碱基以相同顺序出现在S1和S2中(不必是连续的),S3越长,则串S1与S2的相似性越大。在我们所给出的例子中,S3='GTCGTCGGAAGCCGGCCGAA'。
本篇文章将使用动态规划法求解两个字符串的最长公共子序列的函数,并用Java语言编写该函数。
解题思路
动态规划求解最长公共子序列问题,设s1和s2分别为两个字符串,定义dp[i][j]为s1的前i个字符和s2的前j个字符的最长公共子序列长度,则有状态转移方程:
- 当s1[i] == s2[j]时,dp[i][j] = dp[i-1][j-1]+1
- 当s1[i] != s2[j]时,dp[i][j] = max(dp[i-1][j], dp[i][j-1])
最后的dp[s1.length()][s2.length()]就是最长公共子序列的长度,可以用反推法求出最长公共子序列。
Java代码
class CommonOrder {
static StringBuffer s1;// save string1
static StringBuffer s2;// save string2
static StringBuffer s3;// save commom string
CommonOrder(String str1,String str2) {
s1=new StringBuffer(str1);
s2=new StringBuffer(str2);
s3=new StringBuffer();
}
/* 你编写的subsequenceOrder()函数的代码将被嵌在这里 */
StringBuffer getCommonString() {
return s3;
}
}
public class Main {
public static void main(String[] args) {
String X = null,Y = null;
Scanner sc=new Scanner(System.in);
if(sc.hasNext()) X=sc.nextLine();
if(sc.hasNext()) Y=sc.nextLine();
CommonOrder co=new CommonOrder(X,Y);
co.subsequenceOrder();
StringBuffer str=co.getCommonString();
System.out.println(str+' '+str.length());
}
}
输入样例
abcbdabc
acbbdabdbcb
输出样例
acbdabc 7
代码解释
-
subsequenceOrder()函数:
- 首先创建一个二维数组dp,大小为(s1.length()+1) * (s2.length()+1),用于存储状态转移信息。
- 初始化dp[0][j]和dp[i][0]为0,因为空字符串的长度为0。
- 循环遍历s1和s2字符串,根据状态转移方程更新dp数组。
- 最后通过反推法从dp[s1.length()][s2.length()]开始,根据状态转移方程找到最长公共子序列,并将结果存储在s3中。
-
Main函数:
- 从控制台读取输入的两个字符串X和Y。
- 创建CommonOrder对象,并将X和Y传入构造函数。
- 调用subsequenceOrder()函数计算最长公共子序列。
- 打印s3和其长度。
总结
本文详细介绍了使用Java语言和动态规划算法求解两个字符串的最长公共子序列(LCS)问题。提供了代码示例和详细的解题思路,帮助读者理解并掌握LCS算法的实现方法。该算法在生物信息学、文本处理等领域有着广泛的应用。
原文地址: https://www.cveoy.top/t/topic/ohMr 著作权归作者所有。请勿转载和采集!