最长递增子序列
C语言实现最长递增子序列问题的解决方法

C语⾔实现最长递增⼦序列问题的解决⽅法本⽂实例展⽰了C语⾔实现最长递增⼦序列问题的解决⽅法。
分享给⼤家供⼤家参考。
具体⽅法如下:问题描述:给定⼀个序列,找出其最长递增⼦序列长度。
⽐如输⼊ 1 3 7 5输出 3算法解决思路:利⽤动态规划的思想,以序列的每个点最为最右端,找出每个点作为最右端时的⼦序列长度的最⼤值,即问题的求解。
因此,在计算前⾯的每个点的时候,将其结果保存下来,后⾯的点与前⾯的点的数值进⾏⽐较,如果⼤,则在其长度基础上加1,并且找出所有可能情况下最长的保存为当前点的长度。
形成递归。
具体实现代码如下:#include "stdio.h"#include "stdlib.h"#define MAXDATA 10000int main(){int data[MAXDATA]; /*数据序列*/int lgs[MAXDATA]; /*最长⼦序列长度*/int n,temp,k; /*n 序列长度 temp ⼦序列长度中间变量 */scanf("%d",&n);if(n>10000){return 0;}for(int i=0;i<n;i++){scanf("%d",&data[i]);}for(int i=0;i<MAXDATA;i++){lgs[i]=1; /*给每⼀个序列点作为右端时的最⼤序列长度为1*/}for(int i=1;i<n;i++){temp=1;for(int j=0;j<i;j++){ /*与其前⾯的每⼀个进⾏⽐较*/if(data[i]>data[j]){ /*如果数据⽐前⾯的某⼀个的值⼤*/if(lgs[i]+lgs[j]>temp){ /*找出该点的最⼤⼦序列长度*/temp=lgs[i]+lgs[j];}}}lgs[i]=temp;}temp=lgs[0];for(int i=1;i<n;i++){if(lgs[i]>temp){temp=lgs[i];}}printf("%d",temp);system("pause");}希望本⽂所述对⼤家C程序算法设计的学习有所帮助。
动态基础设计实验报告(3篇)

第1篇一、实验目的1. 理解动态规划的基本思想和方法。
2. 掌握动态规划在解决实际问题中的应用。
3. 提高编程能力和算法设计能力。
二、实验内容本次实验主要涉及以下四个问题:1. 斐波那契数列2. 最长公共子序列3. 最长递增子序列4. 零钱找零问题三、实验原理动态规划是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。
动态规划的基本思想是将一个复杂问题分解成若干个相互重叠的子问题,然后按照子问题的顺序逐个求解,最后将这些子问题的解合并成原问题的解。
四、实验步骤及代码实现1. 斐波那契数列斐波那契数列是指这样一个数列:1, 1, 2, 3, 5, 8, 13, 21, ...,其中每个数都是前两个数的和。
```cppinclude <iostream>using namespace std;int Fibonacci(int n) {if (n <= 1) {return 1;}int fib[n+1];fib[0] = 1;fib[1] = 1;for (int i = 2; i <= n; i++) {fib[i] = fib[i-1] + fib[i-2];}return fib[n];}int main() {int n;cout << "请输入斐波那契数列的项数:" << endl;cin >> n;cout << "斐波那契数列的第 " << n << " 项为:" << Fibonacci(n) << endl;return 0;}```2. 最长公共子序列给定两个序列A和B,找出它们的公共子序列中长度最长的序列。
```cppinclude <iostream>using namespace std;int LCSLength(string X, string Y) {int m = X.length();int n = Y.length();int L[m+1][n+1];for (int i = 0; i <= m; i++) {for (int 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;elseL[i][j] = max(L[i-1][j], L[i][j-1]);}}return L[m][n];}int main() {string X = "AGGTAB";string Y = "GXTXAYB";cout << "最长公共子序列长度为:" << LCSLength(X, Y) << endl; return 0;}```3. 最长递增子序列给定一个序列,找出它的最长递增子序列。
最长递增子序列vue3diff算法

最长递增子序列vue3diff算法Vue.js是一款流行的前端框架,它的最新版本Vue 3引入了一种新的diff算法,称为最长递增子序列(Longest Increasing Subsequence,简称LIS)算法。
本文将详细介绍Vue 3中的diff 算法,并探讨它的优势和应用。
在前端开发中,diff算法用于比较两个虚拟DOM树的差异,并将这些差异应用于实际的DOM树上,从而实现高效的页面更新。
Vue 3的diff算法采用了最长递增子序列算法来优化比较过程,提高了性能和效率。
最长递增子序列算法是一个经典的动态规划算法,用于寻找给定序列中最长的递增子序列。
在Vue 3中,这个算法被应用于比较虚拟DOM树的过程中,以减少比较的次数,从而提高性能。
在传统的diff算法中,通常会使用深度优先遍历的方式比较两个DOM树的每个节点。
这种方式的效率较低,尤其是当节点数量较多时,比较的时间复杂度会很高。
而采用最长递增子序列算法,可以将比较的次数减少到最少。
最长递增子序列算法的核心思想是,将待比较的序列转化为一个新的序列,使得新序列的最长递增子序列的长度最大。
在Vue 3中,这个新序列就是由虚拟DOM节点的唯一标识符组成的序列。
通过比较这个新序列的最长递增子序列,可以确定哪些节点需要进行更新,哪些节点可以保持不变。
采用最长递增子序列算法的diff过程如下:1. 遍历新旧虚拟DOM树的所有节点,为每个节点生成唯一标识符。
2. 将新旧虚拟DOM树的节点按照唯一标识符的顺序进行排序。
3. 使用最长递增子序列算法比较排序后的节点序列,得到最长递增子序列。
4. 根据最长递增子序列确定哪些节点需要更新,哪些节点可以保持不变。
5. 将需要更新的节点进行更新操作,将不需要更新的节点保持不变。
通过采用最长递增子序列算法,Vue 3的diff过程可以大大减少比较的次数,提高了性能和效率。
尤其是在页面更新频繁的情况下,这种优化效果更为明显。
动态规划的基本原理和基本应用

动态规划的基本原理和基本应用动态规划(Dynamic Programming)是一种通过将一个问题分解为较小的子问题并存储子问题的解来解决复杂问题的方法。
动态规划的基本原理是通过记忆化或自底向上的迭代方式来求解问题,以减少不必要的重复计算。
它在计算机科学和数学中具有广泛的应用,尤其是在优化、组合数学和操作研究等领域。
1.确定最优子结构:将原问题分解为较小的子问题,并且子问题的最优解能够推导出原问题的最优解。
2.定义状态:确定存储子问题解的状态变量和状态方程。
3.确定边界条件:确定初始子问题的解,也称为边界状态。
4.递推计算:利用状态方程将子问题的解计算出来,并存储在状态变量中。
5.求解最优解:通过遍历状态变量找到最优解。
1.背包问题:背包问题是动态规划的经典应用之一、它有多种变体,其中最基本的是0/1背包问题,即在限定容量的背包中选择物品,使得所选物品的总价值最大。
可以使用动态规划的思想来解决背包问题,确定状态为背包容量和可选物品,递推计算每个状态下的最优解。
2. 最长递增子序列:最长递增子序列(Longest Increasing Subsequence)是一种常见的子序列问题。
给定一个序列,找到其中最长的递增子序列。
可以使用动态规划来解决这个问题,状态可以定义为以第i个元素为结尾的最长递增子序列的长度,并递推计算每个状态的解。
3.矩阵链乘法:矩阵链乘法是一种优化矩阵连乘计算的方法。
给定一系列矩阵,求解它们相乘的最小计算次数。
可以使用动态规划解决矩阵链乘法问题,状态可以定义为矩阵链的起始和结束位置,递推计算每个状态下最小计算次数。
4.最短路径问题:最短路径问题是在有向图或无向图中找到两个节点之间最短路径的问题。
可以使用动态规划解决最短路径问题,状态可以定义为起始节点到一些节点的最短距离,递推计算每个状态的最优解。
动态规划-最长单调递增子序列(dp)

动态规划-最长单调递增⼦序列(dp)解题思想:动态规划1.解法1(n2) 状态:d[i] = 长度为i+1的递增⼦序列的长度 状态转移⽅程:dp[i] = max(dp[j]+1, dp[i]);分析:最开始把dp数组初始化为1,然后从前往后考虑数列的元素,对于每个aj,如果a[i] > a[j],就⽤dp[i] = max(dp[i], dp[j] + 1)进⾏更新,再从dp数组中找出最⼤值即为结果举例:abklmncdefg dp[0] = 1; dp[1] = 2; dp[2] = 3; dp[3] = 4; dp[4] = 5; dp[5] = 6; dp[7] = 3; dp[8] = 4; dp[9] = 5; dp[10] = 6; dp[11] = 7; 最⼤值为7 代码:1 #include<iostream>2 #include<cstdio>3 #include<cstring>4using namespace std;5const int MAX_N = 10005;6int n;7char a[MAX_N];8int dp[MAX_N];9int main() {10int n;11 cin >> n;12while(n--) {13int ans = 0;14 fill(dp, dp+MAX_N, 1);15 cin >> a;16int len = strlen(a);17for(int i = 0; i < len; i++) {18for(int j = 0; j < i; j++) {19if(a[j] < a[i]) dp[i] = max(dp[i], dp[j] + 1);20 }21 ans = max(ans, dp[i]);22 }23 cout << ans << endl;24 }25return0;26 }View Code2.解法2(n2) 状态:d[i] = 长度为i+1的递增⼦序列中末尾的最⼩值(不存在就是INF) 分析:最开始⽤INF初始化dp数组的值,然后从前往后考虑数列的元素,对于每个aj,如果i = 0或者a[j] >= a[i],使得a[j] = a[i]并且break出来,最后第⼀个dp数组中值为INF的下标即为结果 举例:abklmncdefg a; ab; abk; abkl; abklm; abklmn; abclmn; abcdmn; abcden; abcdef; abcdefg; 第⼀个INF的下标为7 代码:1 #include<iostream>2 #include<cstdio>3 #include<cstring>4using namespace std;5const int MAX_N = 10005;6const int INF = 127;7int n;8char a[MAX_N];9char dp[MAX_N];10int main() {11int n;12 cin >> n;13while(n--) {14 fill(dp, dp+MAX_N, INF);15 cin >> a;16int len = strlen(a);17for(int i = 0; i < len; i++) {18for(int j = 0; j < len; j++) {19if(!i || dp[j] >= a[i]) {20 dp[j] = a[i]; break;21 }22 }23 }24int ans = 0;25while(dp[ans] != INF) ans++;26 cout << ans << endl;27 }28return0;29 }View Code3.解法3(nlogn) 分析:思路与解法2⼀样,但是解法2可以进⼀步优化,在解法2中dp数组是单调递增的,每次要从头到尾找到第⼀个⼤于等于a[i]的值,这是o(n2)的,既然是顺序的可以使⽤⼆分查找进⾏改进, 这样可以在o(nlogn)时间内求出结果,这⾥利⽤到了STL中的lower_bound(dp, dp + n, a[i]),找出dp数组中⼤于等于a[i]的最⼩的指针,upper_boundlower_bound(dp, dp + n, a[i]),找出dp数组中⼤于a[i]的最⼤的指针代码:1 #include<iostream>2 #include<cstdio>3 #include<cstring>4 #include<algorithm>5using namespace std;6const int MAX_N = 10005;7const int INF = 127;8int n;9char a[MAX_N];10char dp[MAX_N];11int main() {12int n;13 cin >> n;14while(n--) {15 fill(dp, dp+MAX_N, INF);16 cin >> a;17int len = strlen(a);18for(int i = 0; i < len; i++) {19 *lower_bound(dp, dp+len, a[i]) = a[i];20 }21 cout << lower_bound(dp, dp+len, INF) - dp << endl;22 }23return0;24 }View Code。
动态规划算法原理与的应用

动态规划算法原理与的应用动态规划算法是一种用于求解最优化问题的常用算法。
它通过将原问题划分为子问题,并将每个子问题的解保存起来,以避免重复计算,从而降低了问题的时间复杂度。
动态规划算法的核心思想是自底向上地构建解,以达到求解整个问题的目的。
下面将介绍动态规划算法的原理以及一些常见的应用。
1.动态规划算法的原理1)将原问题划分为多个子问题。
2)确定状态转移方程,即找到子问题之间的关系,以便求解子问题。
3)解决子问题,并将每个子问题的解保存起来。
4)根据子问题的解,构建整个问题的解。
2.动态规划算法的应用2.1最长公共子序列1) 定义状态:假设dp[i][j]表示序列A的前i个字符和序列B的前j个字符的最长公共子序列的长度。
2) 确定状态转移方程:若A[i] == B[j],则dp[i][j] = dp[i-1][j-1] + 1;若A[i] != B[j],则dp[i][j] = max(dp[i-1][j],dp[i][j-1])。
3) 解决子问题:从前往后计算dp数组中每个元素的值。
4) 构建整个问题的解:dp[m][n]即为最终的最长公共子序列的长度,其中m和n分别为序列A和序列B的长度。
2.2背包问题背包问题是指给定一个背包的容量和一些物品的重量和价值,要求在不超过背包容量的情况下,选择若干物品放入背包中,使得背包中物品的总价值最大。
该问题可通过动态规划算法求解,具体步骤如下:1) 定义状态:假设dp[i][j]表示在前i个物品中选择若干物品放入容量为j的背包中,能够获得的最大价值。
2) 确定状态转移方程:考虑第i个物品,若将其放入背包,则dp[i][j] = dp[i-1][j-wi] + vi;若不将其放入背包,则dp[i][j] = dp[i-1][j]。
3) 解决子问题:从前往后计算dp数组中每个元素的值。
4) 构建整个问题的解:dp[n][C]即为最终的背包能够获得的最大价值,其中n为物品的个数,C为背包的容量。
动态规划之最长递增子序列(LIS)

动态规划之最长递增⼦序列(LIS)在⼀个已知的序列{ a1,a2,……am}中,取出若⼲数组成新的序列{ ai1, ai2,…… aim},其中下标 i1,i2, ……im保持递增,即新数列中的各个数之间依旧保持原数列中的先后顺序,那么称{ ai1, ai2,……aim}为原序列的⼀个⼦序列。
若在⼦序列中,当下标 ix > iy时,aix > aiy,那么称其为原序列的⼀个递增⼦序列。
最长递增⼦序列问题就是在⼀个给定的原序列中,求得其最长递增⼦序列的长度。
求最长递增⼦序列的递推公式为:F(1) = 1;F(i) = max{ 1, F[j]+1 | aj<ai && j<i}拦截导弹题⽬描述某国为了防御敌国的导弹袭击,开发出⼀种导弹拦截系统。
但是这种导弹拦截系统有⼀个缺陷:虽然它的第⼀发炮弹能够到达任意的⾼度,但是以后每⼀发炮弹都不能⾼于前⼀发的⾼度。
某天,雷达捕捉到敌国的导弹来袭,并观测到导弹依次飞来的⾼度,请计算这套系统最多能拦截多少导弹。
拦截来袭导弹时,必须按来袭导弹袭击的时间顺序,不允许先拦截后⾯的导弹,再拦截前⾯的导弹。
输⼊描述:每组输⼊有两⾏,第⼀⾏,输⼊雷达捕捉到的敌国导弹的数量k(k<=25),第⼆⾏,输⼊k个正整数,表⽰k枚导弹的⾼度,按来袭导弹的袭击时间顺序给出,以空格分隔。
输出描述:每组输出只有⼀⾏,包含⼀个整数,表⽰最多能拦截多少枚导弹。
⽰例1输⼊8300 207 155 300 299 170 158 65输出6解题思路:要求最多能拦截多少枚导弹,即在按照袭击顺序排列的导弹⾼度中求其最长不增⼦序列。
其中F(1) = 1;F(i) = max{ 1, F[j]+1 | aj>=ai && j<i}1 #include<stdio.h>2 #include<stdlib.h>34int list[26]; //按顺序保存导弹⾼度5int dp[26]; //保存以第i个导弹结尾的最长不增长序列长度6int max( int a,int b)7 {8//选取最⼤值9return a>b? a:b;10 }11int main()12 {13int n;14int tmax,ans;15int i,j;16while( scanf("%d",&n)!=EOF)17 {18for( i=1; i<=n; i++)19 {20 scanf("%d",&list[i]);21 dp[i] = 0;22 }23for( i=1; i<=n; i++)24 {25 tmax = 1; //最长不增长⼦序列长度⾄少为126for( j=1; j<i; j++) //遍历其前所有导弹⾼度27 {28if( list[j]>=list[i]) //若j号导弹不⽐当前导弹低29 {30 tmax = max( tmax,dp[j]+1);31 }32 }33 dp[i] = tmax;34 }35 ans = 1;36for( i=1; i<=n; i++)37 ans = max( ans, dp[i]);38 printf("%d\n",ans);39 }4041return0;42 }。
java算法最长连续递增子序列

java算法最长连续递增⼦序列给定⼀个顺序存储的线性表,请设计⼀个算法查找该线性表中最长的连续递增⼦序列。
例如,(1,9,2,5,7,3,4,6,8,0)中最长的递增⼦序列为(3,4,6,8)。
输⼊格式:输⼊第1⾏给出正整数n(≤105);第2⾏给出n个整数,其间以空格分隔。
输出格式:在⼀⾏中输出第⼀次出现的最长连续递增⼦序列,数字之间⽤空格分隔,序列结尾不能有多余空格。
输⼊样例:1. 152. 1 9 2 5 7 3 4 6 8 0 11 15 17 17 10输出样例:3 4 6 8import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main {public static void main(String[] args) throws IOException {BufferedReader sr = new BufferedReader(new InputStreamReader(System.in));int n=Integer.parseInt(sr.readLine());int[] res=new int[n];String s[] = sr.readLine().split(" ");for(int i=0;i<n;i++)res[i]=Integer.parseInt(s[i]);int max=0,count=0,ss=0,x=0,y=0;for(int i=0;i<n-1;i++) {y=i+1;//判断是否递增,是的话count++;if(res[i+1]>res[i]) {count++;if(count>max) {max=count;ss=x;}}else {count=0;x=y;//不连续递增,则索引改变为下⼀个⽬标}}for(int i=ss;i<=ss+max;i++) {if(i==(ss+max)) {System.out.print(res[i]);}else {System.out.print(res[i]+" ");}}}}实现⼆:public class Sample {public static void main(String[] args) {int []nums = {1,3,4,5,6,7,2,8,9,10};for (int[] lu : findAllLowUpIndex(nums)) {System.out.printf("下标:%d, 上标:%d, 长度%d\n", lu[0], lu[1], lu[1]-lu[0]);}}public static List<int[]> findAllLowUpIndex(int[] nums) {Map<Integer, int[]> map = new HashMap<>(); //map的key是长度,value是数组的上下标for (int i=0, j=0; i<nums.length-1; i++) {for (j=i+1; j<nums.length && nums[j-1]<nums[j]; j++) {map.put(j-i, new int[] {i, j}); //j-i就是长度,i是下标,j是上标,相同长度的返回较⼤的index,所以后来的index直接覆盖之前的信息}}return map.entrySet().stream().sorted((e1,e2)->e1.getKey().compareTo(e2.getKey())) //这⾥是为了按长度排序.map(e->e.getValue()).collect(Collectors.toList()); //这⾥是去掉长度信息只保留上下标信息 }}实现三:public class Test3 {public static void main(String[] args) {int[] nums = new int[]{5, 6, 7, 0,1, 2, 3, 8, 4, 5, 7, 9, 21};calc(nums);}public static void calc(int[] nums) {int[] max = null;int start = 0;int end = 0;for (int i = 1; i < nums.length; i++) {int pre = nums[i - 1];int cur = nums[i];if (cur > pre) {end = i;}if (cur <= pre || i == nums.length - 1) {if (max == null || max[1] - max[0] <= end - start) {max = new int[]{start, end};}start = i;}}System.out.println(String.format("[%s,%s]", max[0], max[1]));}}实现四:public class Sample {public static void main(String[] args) {int []nums = {1,3,4,5,6,7,2,8,9,10,3,4,5,6,7,1,8,6,5};for (int[] lu : findAllLowUpIndex(nums)) {System.out.printf("y:%d=>%d\n", lu[0], lu[1]);}}public static List<int[]> findAllLowUpIndex(int[] nums) {List<int[]> result = new ArrayList<>();for (int i=0, j=0; i<nums.length-1; i=j) {for (j=i+1; j<nums.length && nums[j-1]<nums[j]; j++);if (j-1>i) { //长度为2以上则保存结果result.add(new int[] {i, j-1});}}return result;}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
vara,f{DP记录},p{后面的}:array[1..1000]of longint;i,j,k,n:longint;beginreadln(n);for i:=1 to n dobeginread(a[i]);f[i]:=1;{预处理}end;for i:=n-1 downto 1 dofor j:=n downto i+1 doif (a[i]<a[j])and(f[i]<=f[j])then beginp[i]:=j;f[i]:=f[j]+1;end;k:=0;for i:=n downto 1 doif f[i]>jthen beginj:=f[i];k:=i;end;writeln(j);while k<>0 dobeginwrite(k,' ');k:=p[k];end;end.最长上升子序列的nlog(n)算法[ 2007-7-7 8:26:00 | By: TINYWOLF ]听说程序是cqf大牛d ^_^刚开始一看,以为a数组是用来保存元素的,呵呵,特点1:每次输入一个元素都要进行处理,以求维护好整个数组。
那为什么要维护要整个数组呢?假设最长可以达到i,那么1<k<i,a[k]永远表示当前状态下所有第k长的子序列中第k个中最小的那个值(就是a的确是用来保存数组的啦,但是又不是那么单纯)如果输入一个元素t,比最大的那个大,那好办 if(t>a[c-1]) a[c++]=t;如果不是呢,那t要插进数组里面去,代替一个没有必要存在的元素,为什么说它没有必要呢?比如 1 3 5 6 7 8 4 6 9前面都是比较顺,所以一下子积累到了1 3 5 6 7 8 ,接着来了一个4这个4要代替5,而且这样做一点都不影响最后的结果(只会变好不会变坏)因为如果后来再来一个5就可以代替6的位置了,哈哈,下来的工作就交给cqf大牛的程序了 ^_^ -特点2:二分那里,一来为了更快找到代替元素,而来要注意上下指针的改变不一样,要代替的是比自己刚好大那么一dd(最小)的那个。
#i nclude<stdio.h>#i nclude<string.h>int main(){int a[40005],c,m,n,i,k,t;scanf("%d",&m);while(m-->0){scanf("%d",&n);if(n==0){printf("0\n");continue;}for(i=0;i<=n+2;i++)a[i]=0;c=1;scanf("%d",&t);a[0]=t;for(k=1;k<n;k++){scanf("%d",&t);if(t>a[c-1]) a[c++]=t;else{int l=0,h=c-1,mid=(l+h)/2;while(l<h){if(a[mid]<t)l=mid+1; //而来要注意上下指针的改变不一样else if(a[mid]>t)h=mid;mid=(l+h)/2;}a[mid]=t;}}printf("%d\n",c);}return 0;}Zju 1986 Bridging Signals阅读全文(89) | 回复(3) | 引用通告(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 的最长公共子序列由性质导出子问题的递归结构当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] }////////////////////////////////////////这种分析方法我总得比较有用,值得保存,所以就从book----《计算机机算法设计与分析》电子工业出版社中摘录出来,如果不明白,可以看一看原作。
////////////////////////////////////////// 书中只有关键部分的代码,现在已经补全// 源程序#include "iostream.h"#include "iomanip.h"#define max 100void LCSLength( int m , int n , char *x , char *y , char *b ) {int i , j , k;int c[max][max];for( i = 1 ; i <= m ; i++ ){c[i][0] = 0;}for( i = 1 ; i <= n ; i++ ){c[0][i] = 0;}for( i = 1 ; i <= m ; i++ ){for( j = 1 ; j <= n ; j++ ){if( x[i-1] == y[j-1] ){c[i][j] = c[i-1][j-1] + 1;k = i * ( n + 1 ) + j;b[k] = '\\';}else if( c[i-1][j] >= c[i][j-1] ){c[i][j] = c[i-1][j];k = i * ( n + 1 ) + j;b[k] = '|';}else{c[i][j] = c[i][j-1];k = i * ( n + 1 ) + j;b[k] = '-';}}}}void LCS( int i , int j , char *x , char *b , int width ) {if( i == 0 || j == 0 )return;int k = i * ( width + 1 ) + j;if( b[k] == '\\' ){LCS( i - 1 , j - 1 , x , b , width );cout<<x[i]<<endl;}else if( b[k] == '|' ){LCS( i - 1 , j , x , b , width );}else{LCS( i , j - 1 , x , b , width );}}void main(){char x[max] = { 'a' , 'b' , 'c' , 'b' , 'd' , 'a' , 'b' }; char y[max] = { 'b' , 'd' , 'c' , 'a' , 'b' , 'a' };int m = 7;int n = 6;char b[max] = { 0 };LCSLength( m , n , x , y , b );LCS( m , n , x , b , n );cout<<endl<<endl;}////////////////////////////////////////参考资料:最长公共子序列问题LCS问题描述一个给定序列的子序列是在该序列中删去若干元素后得到的序列。
确切地说,若给定序列X=<x1, x x m>,则另一序列Z=<z1, z2,…, z k>是X的子序列是指存在一个严格递增的下标序列 <i1, i2,…, 2,…,i k>,使得对于所有j=1,2,…,k有例如,序列Z=<B,C,D,B>是序列X=<A,B,C,B,D,A,B>的子序列,相应的递增下标序列为<2,3,5,7>。
给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
例如,若X=<A, B, C, B, D, A, B>和Y=<B, D, C, A, B, A>,则序列<B, C, A>是X和Y的一个公共子序列,序列<B, C, B, A>也是X和Y的一个公共子序列。
而且,后者是X和Y的一个最长公共子序列,因为X和Y没有长度大于4的公共子序列。
最长公共子序列(LCS)问题:给定两个序列X=<x1, x2, …, x m>和Y=<y1, y2, … , y n>,要求找出X和Y的一个最长公共子序列。
参考解答动态规划算法可有效地解此问题。
下面我们按照动态规划算法设计的各个步骤来设计一个解此问题的有效算法。
1.最长公共子序列的结构解最长公共子序列问题时最容易想到的算法是穷举搜索法,即对X的每一个子序列,检查它是否也是Y的子序列,从而确定它是否为X和Y的公共子序列,并且在检查过程中选出最长的公共子序列。
X 的所有子序列都检查过后即可求出X和Y的最长公共子序列。
X的一个子序列相应于下标序列{1, 2,…, m}的一个子序列,因此,X共有2m个不同子序列,从而穷举搜索法需要指数时间。
事实上,最长公共子序列问题也有最优子结构性质,因为我们有如下定理:定理: LCS的最优子结构性质设序列X=<x1, x2, …, x m>和Y=<y1, y2, …, y n>的一个最长公共子序列Z=<z1, z2, …, z k>,则:1.若x m=y n,则z k=x m=y n且Z k-1是X m-1和Y n-1的最长公共子序列;2.若x m≠y n且z k≠x m ,则Z是X m-1和Y的最长公共子序列;3.若x m≠y n且z k≠y n,则Z是X和Y n-1的最长公共子序列。