最长公共子序列(动态规划解决)
其中:某个序列的子序列定义为原序列中的0个或多个元素被去掉之后剩下的元素序列。
给定两个序列
X = { x1 , x2 , … , xm }
Y = { y1 , y2 , … , yn }
求X和Y的一个最长公共子序列
举例
X = { a , b , c , b , d , a , b }
Y = { b , d , c , a , b , a }
最长公共子序列为
LSC = { b , c , b , a }
分析:
最长公共子序列问题具有最优子结构性质
设
X = { x1 , … , xm }
Y = { y1 , … , yn }
及它们的最长子序列
Z = { z1 , … , zk }
则
1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列
2、若 xm != yn ,且 zk != xm ,
则 Z 是 X[m-1] 和 Y 的最长公共子序列
3、若 xm != yn , 且 zk != yn , 则 Z 是 Y[n-1] 和 X 的最长公共子序列
定义c[i,j]为序列Xi和Yj的最长公共子序列的长度,由性质导出子问题的递归结构
当 i = 0 , j =
0 时 , c[i][j] = 0
当 i , j >
0 ; xi = yi 时 , c[i][j] =
c[i-1][j-1] + 1
当 i , j >
0 ; xi != yi 时 , c[i][j] =
max { c[i][j-1] , c[i-1][j] }
在这个公式的基础上不难得到一个指数复杂度的递归算法求最长公共子序列,但是考虑到对长度分别为m, n的序列X, Y,其前缀分别有m+1, n+1个,不同的子问题个数的最多有(m+1)(n+1)个,可以用动态规划法自底向上求解。算法是:
对给定的xm , yn
1、如果m=0或者n=0,返回0,算法结束。
2、建立数组c[m+1][n+1],将c[0][0..n],
c[0..m][0]初始化为0。[注:c[i][j]在i=0或j=0时取值为0。]
3、按照从左到右,从上到下的顺序填表。对c[i][j]来说,如果xi=yj,那么令delta=1,
c[i][j]的值是以下三者中最大的一个:c[i-1][j], c[i][j-1], c[i-1][j-1]+delta。
4、表c填满后,c[m][n]的值就是最大公共子序列的长度。
5、填表过程结束后,按照第3步的规则倒推,即可知道哪些i,
j的值是出现在最长公共子序列中的下标。
代码如下:
String mStr1 = "abefcadasda";
String mStr2 = "abkcefaasd";
// 公共子序列长度
int[][] mLength = new int[mStr1.length() + 1][mStr2.length() + 1];
//路径
String[][] mPath = new String[mStr1.length() + 1][mStr2.length() + 1];
// 计算最长公共序列的长度以及记录路径
public void LCS(String s1, String s2) {
for (int i = 0; i < s1.length(); i++) {
mLength[i][0] = 0;
}
for (int j = 0; j < s2.length(); j++) {
mLength[0][j] = 0;
}
for (int i = 0; i < s1.length(); i++) {
for (int j = 0; j < s2.length(); j++) {
// 字符相等,表中数据加1,用“↖”表示从对角线返回
if (s1.charAt(i) == s2.charAt(j)) {
mLength[i + 1][j + 1] = mLength[i][j] + 1;
mPath[i + 1][j + 1] = "↖";
}
// 当前两个字符不相等,表中数据继承上方的数据,用“↑”表示向上返回
else if (mLength[i][j + 1] >= mLength[i + 1][j]) {
mLength[i + 1][j + 1] = mLength[i][j + 1];
mPath[i + 1][j + 1] = "↑";
}
// 表中数据继承左方的数据,用“←”表示向左返回
else {
mLength[i + 1][j + 1] = mLength[i + 1][j];
mPath[i + 1][j + 1] = "←";
}
}
}
}// end LCS
// 输出最长公共序列
public void print_LCS(String[][] path, String str1, int str1_length, int str2_length) {
// 其中一个字符串为空,返回
if (str1_length == -1 || str2_length == -1) {
return;
}
// 对角线返回
if (path[str1_length + 1][str2_length + 1] == "↖") {
print_LCS(path, str1, str1_length - 1, str2_length - 1);
System.out.print(str1.charAt(str1_length));
}
// 向上返回
else if (path[str1_length + 1][str2_length + 1] == "↑") {
print_LCS(path, str1, str1_length - 1, str2_length);
}
// 向左返回
else
print_LCS(path, str1, str1_length, str2_length - 1);
}// end print_LCS
public static void main(String[] args) {
LCSProblem lcs = new LCSProblem();
lcs.LCS(lcs.mStr1, lcs.mStr2);
lcs.print_LCS(lcs.mPath, lcs.mStr1, lcs.mStr1.length() - 1, lcs.mStr2.length() - 1);
System.out.print(" length:"+lcs.mLength[lcs.mStr1.length()][lcs.mStr2.length()]);
}
分享到:
相关推荐
最长公共子序列(Longest Common Subsequence,LCS)是一个经典的计算机科学问题,涉及序列比较和算法设计。在本实验报告中,我们将深入探讨如何利用动态规划方法解决这一问题。 首先,LCS问题旨在找到两个给定序列...
动态规划中的最长公共子序列 动态规划中的最长公共子序列是指给定两个序列 X 和 Y,找到他们的最长公共子序列的长度和该子序列本身。该问题是计算机科学中的一类典型问题,广泛应用于数据压缩、数据挖掘、生物信息...
最长公共子序列(Longest Common Subsequence,LCS)是一个经典的计算机科学问题,它涉及到序列比对和字符串处理。在两个或多个序列中,LCS是指没有改变原有顺序的情况下,存在于所有序列中的最长子序列。这个问题在...
### 最长公共子序列问题详解 #### 一、问题定义及背景 最长公共子序列(Longest Common Subsequence,简称LCS)问题属于计算机科学领域中的一个重要问题,尤其是在算法设计与分析方面。此问题的核心在于寻找两个...
实验报告的主题是“算法设计与分析”,关注的是使用动态规划解决最长公共子序列(Longest Common Subsequence, LCS)的问题。动态规划是一种有效的方法,它适用于具有最优子结构和子问题重叠性质的问题。在本实验中...
### 最长公共子序列算法总结 #### 一、O(n^2)算法 在讨论最长公共子序列(Longest Common Subsequence,简称LCS)问题时,通常会提及两种主要的算法实现方式:一种时间复杂度为O(n^2),另一种则通过优化达到O...
### C++实现最长公共子序列算法详解 在深入解析给定代码之前,我们先来了解一下“最长公共子序列”(Longest Common Subsequence,简称LCS)的基本概念及其在计算机科学中的应用。LCS问题是一种典型的动态规划问题...
【最长公共子序列(动态规划)】是一种经典的算法问题,主要应用于序列比对、文本处理等领域。本实验报告详尽地介绍了如何运用动态规划解决这一问题。 动态规划是一种解决复杂问题的有效方法,它通过将大问题分解为...
### 实验三:最长公共子序列 #### 实验目的 本次实验旨在使学生掌握如何运用动态规划策略来解决最长公共子序列(Longest Common Subsequence, LCS)问题,并通过编程实践加深对动态规划算法的理解。 #### 实验原理...
### 最长公共子序列动态规划算法 在计算机科学领域中,**最长公共子序列问题**(Longest Common Subsequence Problem, LCS)是一个经典的算法问题,它主要应用于文本比较、生物信息学中的DNA序列比对等领域。该问题...
算法工程项目问题描述: 【题目】 动态规划思维训练——最长公共子序列算法的设计与实现 给定两个序列X={X1, X2,···,Xm}和...字符串Y:{ABCBDAB},则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA
最长公共子序列问题LCS 最长公共子序列问题(Longest Common Subsequence,LCS)是计算机科学中一个经典的问题,它是指给定两个序列X和Y,找出它们的最长公共子序列。该问题具有重要的理论和实际意义,在很多领域都...
### C++ 实现最长公共子序列问题 #### 知识点概述 本篇文章将详细介绍如何使用C++语言解决最长公共子序列(Longest Common Subsequence, LCS)问题,并结合具体的代码示例进行深入剖析。文章将涵盖以下几个核心...
最长公共子序列(Longest Common Subsequence,LCS)是计算机科学中一种经典的字符串问题,主要涉及算法设计和分析。它的目标是找到两个给定序列(通常为字符串)的最长子序列,该子序列在原序列中不需连续,但必须...
根据给定的文件信息,我们可以总结出以下关于“输出最长公共子序列”的C语言实现的知识点: ### 一、最长公共子序列问题介绍 最长公共子序列(Longest Common Subsequence,简称 LCS)是一个经典的计算机科学问题...
最长公共子序列(Longest Common Subsequence,LCS)问题是一个经典的计算机科学问题,主要涉及字符串处理和动态规划算法。在本场景中,我们使用C#编程语言来解决这个问题。C#是一种多范式编程语言,广泛应用于开发...