`
songzi0206
  • 浏览: 158855 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
Group-logo
All are from ...
浏览量:33816
Group-logo
Programming w...
浏览量:19683
社区版块
存档分类
最新评论

动态规划之LCS

 
阅读更多

/**

 * 动态规划之最长公共子序列问题:给定一个子序列 X = <x1,x2,...xm>,另一个子序列Z = <z1,z2,...zk>是X的子序列,如果存在X的一个严格递增下标序列

 * <i1,i2,...ik>,使得对于所有j = 1,2,...k,有xij = zj。如Z=<B,C,D,B>是X=<A,B,C,B,D,A,B>子序列,对应下标i = <2,3,5,7>

 * LCS问题:给定序列X=<x1,x2,...xn>和Y=<y1,y2...ym>,找出X和Y的最长公共子序列

 * 设Z<z1,z2,...zk>是X和Y的任一个最长公共子序列,那么:

 *   1) 若xn = ym,则zk = xn = ym 而且<z1,z2,...zk-1>是Xn-1和Ym-1的最长公共子序列

 *   2) 若xn != ym 则zk!=xn 蕴含Z是Xn-1和Y的一个LCS

 *   3) 若ym != xn 则zk!= ym蕴含Z是x和Ym-1的一个LCS

 *   

 *   基于以上结论,可以得出一个递归解:

 *   定义c[i][j]是序列Xi和Yj的LCS的长度则:

 *              -->  0     if i = 0 或者 j = 0  

 *   c[i][j] =  -->  c[i-1][j-1] + 1   如果i>0,j>0,xi=yj

 *   -->  max{c[i-1][j],c[i][j-1]} 如果i>0,j>0,xi != yj

 * @author song 

 *                

 */

 

	/**
	 * 计算x和y的公共子序列长度表
	 * @param x
	 * @param y
	 * @return
	 */
	public static int[][] calculateCommonSubsequenceNum(char[] x, char[] y){
		int n = x.length;
		int m = y.length;
		//记录各个LCS长度的二维表
		int[][] c = new int[n+1][m+1];
		//初始化:c[i][j] = 0 当i=0 or j=0
		for(int i = 0; i <= m; ++i)
			c[0][i] = 0;
		for(int j = 0; j <= n; ++j)
			c[j][0] = 0;
		//注意c[1][1]记录的是 x[0]和y[0]的公共子序列长度,因为x和y的第一个元素不是x[1]和y[1],而是x[0]和y[0]
		for( int i = 1; i <= n; ++i){
			for(int j = 1; j <= m; ++j){
				if( x[i-1] == y[j-1] )
					c[i][j] = c[i-1][j-1] + 1;
				else{
					c[i][j] = Math.max(c[i-1][j], c[i][j-1]);
				}
			}
		}
		return c;
	}
 /**
	 * 找出一个最长公共子序列
	 * 找出LCS依赖于 {@link #calculateCommonSubsequenceNum(char[], char[])}的LCS长度序列表
	 * 根据最初分析的三个结论
	 *    1)若Z是X和Y的LCS,若xn=ym,则zk = xn = ym即X和Y的最后一个字符肯定出现在LCS中
	 *    2)若xn != ym,则Z肯定是  Xn-1和Ym的LCS 以及 Xn和Ym-1的LCS中更长得那一个序列,也就是说当xn!=ym时,可以转化为找  Xn-1和Ym的LCS/ Xn和Ym-1的LCS
	 *         更进一步,若c[n-1][m] > c[n][m-1],找Xn-1和Ym的LCS即可,因为他更长,反之找Xn和Ym-1的LCS
	 *  因此,从后向前扫描x和y序列,碰到相同则将该字符放入LCS,
	 *    若不相同,则比较c[n-1][m] > c[n][m-1],根据他们的值比较xn-1和ym  或者  xn和ym-1
	 *  
	 * @param x
	 * @param y
	 * @return
	 */
	public static List<Character> findLongestLCS(char[] x,char[] y){
		List<Character> result = new LinkedList<Character>();
		int c[][] = calculateCommonSubsequenceNum(x, y);
		int n = x.length - 1;
		int m = y.length - 1;
		while( n >= 0 && m >= 0){
			if(x[n] == y[m]){
				result.add(0, x[n]);
				n--;m--;
			}else{
				if(c[n][m+1] > c[n+1][m])
					n--;
				else
					m--;
			}
		}
		
		return result;
		
	}

 测试代码:

public static void main(String[] args) {
		char[] x = "10010101".toCharArray();
		char[] y = "010110110".toCharArray();
		List<Character> r = findLongestLCS(x, y);
		System.out.println("The longest LCS:" + r.toString());
	}

 result:The longest LCS:[0, 1, 0, 1, 0, 1]

分享到:
评论

相关推荐

    动态规划解决LCS问题

    在本例中,我们将聚焦于“最长公共子序列”(Longest Common Subsequence, LCS)问题,这是一种典型的动态规划应用。 最长公共子序列问题指的是给定两个序列X和Y,找到它们的最长子序列,这个子序列不必是连续的,...

    LCS动态规划算法实现

    动态规划是解决LCS问题的常用方法,它通过构建二维数组来存储子问题的解,从而避免了重复计算,提高了效率。 在动态规划解决LCS问题时,我们通常定义一个二维数组`dp`,其中`dp[i][j]`表示字符串S1的前i个字符与...

    lcs.rar_LCS_动态规划

    理解并掌握动态规划解决LCS问题的方法,对于提升算法能力和解决实际问题具有重要意义。在学习过程中,可以尝试对不同的输入数据进行测试,以加深对动态规划过程的理解,并优化算法性能,如使用空间优化减少存储需求...

    LCS.rar_LCS_Lcs.rar_公共子序列_动态规划

    标题"LCS.rar_LCS_Lcs.rar_公共子序列_动态规划"中,"LCS"代表最长公共子序列(Longest Common Subsequence),这是一个经典的计算机科学问题,特别是在算法和数据结构领域。它涉及到找到两个或更多序列中最长的子...

    LCS.rar_动态规划

    在IT领域,动态规划是一种强大的算法,用于解决各种复杂问题,包括寻找两个序列中的最长公共子序列(Longest Common Subsequence, LCS)。本压缩包"**LCS.rar_动态规划**"显然关注的是如何利用动态规划来处理这个...

    动态规划:最长公共子串 LCS

    ### 动态规划:最长公共子串 LCS #### 长度与定义 **最长公共子串(Longest Common Substring, LCS)**是两个或多个字符串中的最长字符串,该字符串同时也是这些字符串的子串。这里需要注意区分子串与子序列的概念...

    lcs.rar_LCS_lcs dynamic

    例如,“www.pudn.com.txt”可能是某个网站上关于LCS问题的讨论或者示例代码,而“动态规划lcs”可能是作者编写的一个动态规划求解LCS的程序。 通过阅读这些文件,你可以深入理解LCS问题的动态规划解决方案,包括...

    lcs最长公共子序列动态规划

    最长公共子序列(lcs)使用动态规划解决采用c++编写

    【ACM程序设计】动态规划 第二篇 LCS&amp;LIS问题.doc

    "动态规划 LCS&LIS 问题" 动态规划是计算机科学中的一种重要方法,用于解决复杂的问题。今天,我们将讨论动态规划在解决LCS(Longest Common Subsequence)和LIS(Longest Increasing Subsequence)问题中的应用。 ...

    01-F-8 理解LCS & 01-F-9 LCS动态规划1

    LCS 不仅在计算机科学中广泛应用,比如在比较文本、生物信息学等领域,而且是动态规划的经典问题之一。 ### 算法正确性的保证 1. **单调性**: - 在计算LCS的过程中,每次比较两个序列的一个字符后,至少有一个...

    LIS & LCS(动态规划)

    问题描述 东东有两个序列A和B。...这个题是基本的动态规划问题,LIS是最长上升子序列,LCS是最长公共子序列。 求解LIS就是设dp[i]为以当前元素结尾的最长上升序列,那么dp[i]=max(dp[j]∣j&lt;i&&a

    LCS.rar_LCS_lcs dynamic

    标题中的"LCS.rar_LCS_lcs dynamic"表明这是一个关于最长公共子序列(Longest Common Subsequence, LCS)问题的资源包,重点在于动态规划的实现。动态规划是一种解决复杂问题的有效算法,通常用于找到最优化的解决...

    算法动态规划总结(拓展篇)

    背包问题是动态规划的经典应用之一,涉及物品的选择和容量的限制,综合题可能包括0/1背包、完全背包等多种变体。 ### 14. 超级大背包 针对超大规模的背包问题,可能需要更高级的优化技巧和数据结构支持,如优先...

    LCS的实现代码

    最长公共子序列(Longest Common Subsequence,简称LCS)是计算机科学中一种经典的问题,主要涉及到了动态规划这一算法设计思想。在这个问题中,给定两个字符串,目标是找到它们的最长子序列,这个子序列不必连续,...

    最长公共子序列(动态规划)报告.doc

    【最长公共子序列(动态规划)】是一种经典的算法问题,主要应用于序列比对、文本处理等领域。本实验报告详尽地介绍了如何运用动态规划解决这一问题。 动态规划是一种解决复杂问题的有效方法,它通过将大问题分解为...

    LCS.rar_LCS 子问题层叠

    最长公共子序列(Longest Common Subsequence,简称LCS)是计算机科学中一个经典的问题,主要涉及字符串处理、算法设计和动态规划等领域。在给定的两个字符串中,LCS是指不改变顺序的情况下,这两个字符串共有的最长...

    LCS.rar_LCS

    解决LCS问题的经典方法是采用动态规划,这种策略将问题分解为更小的子问题,然后通过构建一个二维数组来存储这些子问题的解。这个二维数组通常称为LCS表,它的大小为m+1(m为字符串A的长度)乘以n+1(n为字符串B的...

    动态规划经典应用

    动态规划是一种强大的算法思想...动态规划的巧妙之处在于其能够将复杂问题分解为更小的子问题,通过存储子问题的解来避免重复计算,从而提高效率。学习并掌握这些经典应用,对于提升你在IT领域的专业技能具有重要意义。

    动态规划 实验报告 背包和LSC

    本实验报告主要关注两个经典的动态规划应用:0-1 背包问题和最长公共子序列问题(LCS)。 1. 0-1 背包问题: 0-1 背包问题是组合优化问题的一个实例,它涉及到在给定的物品集合中选择一些物品放入容量有限的背包中...

    lcs.rar_LCS

    LCS是计算机科学中一个经典的算法问题,主要涉及字符串处理、序列比较和动态规划等领域。在这个问题中,我们的目标是找到两个给定序列中最长的子序列,这个子序列不必连续,但要在两个原始序列中都存在。 描述中...

Global site tag (gtag.js) - Google Analytics