动态规划(篇3)最长公共子序列(LCS)
来源:互联网 发布:unity3d ios 交互 编辑:程序博客网 时间:2024/05/14 21:56
LCS问题陈述:
给定两个序列,找出它们中存在的最长子序列的长度。子序列是以相同的相对顺序出现但不一定是连续的序列。例如,“abc”,“abg”,“bdf”,“aeg”,“acefg”,…等是“abcdefg”的子序列。因此,长度为n的串具有2 ^ n个不同的可能子序列。
示例:
用于输入序列的LCS“ABCDGH”和“AEDFHR”是长度为3的“ADH”。
用于输入序列的LCS“AGGTAB”和“GXTXAYB”是长度为4的“GTAB”
这个问题的原始解决方案是生成两个给定序列的所有子序列,并找到最长匹配的子序列。该解在时间复杂度方面是指数的。让我们看看这个问题如何拥有动态规划(DP)问题的两个重要属性。
1)最优子结构:
使输入序列分别为长度m和n的X [0..m-1]和Y [0..n-1]。并且使L(X [0..m-1],Y [0..n-1])是两个序列X和Y的LCS的长度。 m-1],Y [0..n-1])。
如果两个序列的最后字符匹配(或X [m-1] == Y [n-1]),则
L(X [0..m-1],Y [0..n-1])= L(X [0..m-2],Y [0..n-2])
如果两个序列的最后字符不匹配(或X [m-1]!= Y [n-1]),则
L(X [0..m-1],Y [0..n-1] MAX(L(X [0..m-2],Y [0..n-1]),L(X [0..m-1],Y [0..n-2])
示例:
1)考虑输入字符串“AGGTAB”和“GXTXAYB”。字符串的最后字符匹配。因此LCS的长度可以写为:
L(“AGGTAB”,“GXTXAYB”)= 1 + L(“AGGTA”,“GXTXAY”)
2)考虑输入字符串“ABCDGH”和“AEDFHR。最后字符与字符串不匹配。因此LCS的长度可以写为:
L(“ABCDGH”,“AEDFHR”)= MAX(L(“ABCDG”,“AEDFH R ”),L(“ABCDG H ”,“AEDFH”))
因此,LCS问题具有最佳子结构属性,因为主要问题可以使用子问题的解决方案来解决。
2)重叠子问题:
以下是LCS问题的简单递归实现。该实现简单地遵循上述递归结构。
递归代码:
/* A Naive recursive implementation of LCS problem */#include<bits/stdc++.h>int max(int a, int b);/* Returns length of LCS for X[0..m-1], Y[0..n-1] */int lcs( char *X, char *Y, int m, int n ){ if (m == 0 || n == 0) return 0; if (X[m-1] == Y[n-1]) return 1 + lcs(X, Y, m-1, n-1); else return max(lcs(X, Y, m, n-1), lcs(X, Y, m-1, n));}/* Utility function to get max of 2 integers */int max(int a, int b){ return (a > b)? a : b;}/* Driver program to test above function */int main(){ char X[] = "AGGTAB"; char Y[] = "GXTXAYB"; int m = strlen(X); int n = strlen(Y); printf("Length of LCS is %d\n", lcs( X, Y, m, n ) ); return 0;}
输出:
LCS的长度为4
上述递归方法的时间复杂度在最坏情况下为O(2 ^ n),并且当X和Y的所有字符不匹配,即LCS的长度为0时,发生最坏情况。
考虑上述实现,以下是部分递归树输入字符串“AXYT”和“AYZX”
lcs("AXYT", "AYZX") / \ lcs("AXY", "AYZX") lcs("AXYT", "AYZ") / \ / \lcs("AX", "AYZX") lcs("AXY", "AYZ") lcs("AXY", "AYZ") lcs("AXYT", "AY")
在上述部分递归树中,lcs(“AXY”,“AYZ”)被求解两次。如果我们绘制完整的递归树,那么我们可以看到有很多子问题被一次又一次解决。所以这个问题具有重叠的子结构属性和重新计算相同的子问题可以通过使用记忆或制表避免。以下是LCS问题的列表实现。
动态规划
/* Dynamic Programming C/C++ implementation of LCS problem */#include<bits/stdc++.h>int max(int a, int b);/* Returns length of LCS for X[0..m-1], Y[0..n-1] */int lcs( char *X, char *Y, int m, int n ){ int L[m+1][n+1]; int i, j; /* Following steps build L[m+1][n+1] in bottom up fashion. Note that L[i][j] contains length of LCS of X[0..i-1] and Y[0..j-1] */ for (i=0; i<=m; i++) { for (j=0; j<=n; j++) { if (i == 0 || j == 0) L[i][j] = 0; else if (X[i-1] == Y[j-1]) L[i][j] = L[i-1][j-1] + 1; else L[i][j] = max(L[i-1][j], L[i][j-1]); } } /* L[m][n] contains length of LCS for X[0..n-1] and Y[0..m-1] */ return L[m][n];}/* Utility function to get max of 2 integers */int max(int a, int b){ return (a > b)? a : b;}/* Driver program to test above function */int main(){ char X[] = "AGGTAB"; char Y[] = "GXTXAYB"; int m = strlen(X); int n = strlen(Y); printf("Length of LCS is %d\n", lcs( X, Y, m, n ) ); return 0;}
- 最长公共子序列(LCS)(一)---动态规划
- 动态规划之最长公共子序列(lcs)
- 动态规划之最长公共子序列(lcs)
- 动态规划经典问题---最长公共子序列(LCS)
- 动态规划——最长公共子序列(LCS)
- 最长公共子序列LCS(动态规划基础)
- 最长公共子序列LCS(动态规划)
- 动态规划——最长公共子序列(LCS)
- 动态规划求解最长公共子序列(LCS)
- 动态规划7:最长公共子序列(LCS)
- 动态规划之最长公共子序列(LCS)
- 动态规划之最长公共子序列(LCS)
- 动态规划入门之最长公共子序列(LCS)
- 最长公共子序列(LCS)-动态规划
- 使用动态规划求解最长公共子序列(LCS)
- 动态规划 最长公共子序列(LCS)问题
- 动态规划求解最长公共子序列(LCS)
- LCS问题(最长公共子序列)-动态规划实现
- 存储过程+游标
- HTTP协议/IIS 原理及ASP.NET运行机制浅析
- 常用的sql查询
- ACM刷题之Hdu ————How Many Tables
- WebDriver介绍
- 动态规划(篇3)最长公共子序列(LCS)
- Spring学习心得(18)-- 通知的种类
- 第一、Java的开发前奏
- cuda8+cuDNN Faster R-CNN安装塈运行demo
- 《百度URL采集器》
- 射频识别技术漫谈(10)——识别号的格式变化
- MyBatis之动态SQL
- 条款06:若不想使用编译器自动生成的函数,就该明确拒绝
- 35. Search Insert Position