序列最的问题之最长公共子序列LCS

  在程序设计竞赛中,我们时常会遇到序列求最值的问题。在讲今天的问题之前,先小小的说明一下,子序列与子串的问题。

  子序列:在原序列中不一定连续;

  子串:在原序列中必须连续。

  接下来,就开始今天要讲的最长公共子序列LCS(Longest Common
Subsequence).对于LCS这一类的问题,一般是相对于两个序列而言,str[]与ch[]。先假设str的长度为n,ch的长度为m。假设str[]="ASBDAH",ch[]="SDAAH";其中"SDA"是其中的str与ch的一个子序列,但不是最长的。最长的子序列为"SDAH",当然,有时候我们会看到两个串中有多个相同长度的子序列,这不足为奇。

  如果我们枚举str的子序列,那么将有2n个子序列,这很不切实际。因此我们可以试着让str中前1,2,3……n参与的情况下分别与ch串中前1,2……m参与情况求出LCS。

  

  dp[i][j]表示str前i个参与,以及ch前j个参与的LCS。

  当str[i] == ch[j]时,只需要记录统计出str[1~i - 1],ch[1~j -
1]的LCS,在此基础上加1.

  当str[i] != ch[j]时,我们只需要求str[1 ~ i - 1]且ch[1~j],str[1 ~
i]且ch[1~j-1]的最大值即可。

  

 1 #include <iostream>
2 #include <string.h>
3 #include <stdio.h>
4 #include <math.h>
5 using namespace std;
6 const int MAX = 100 + 10;
7 char str[MAX], ch[MAX];
8 int dp[MAX][MAX];
9
10 int max(int a, int b){ return a > b ? a : b;}
11
12 int main()
13 {
14 int t, n, m;
15 scanf("%d", &t);
16 getchar();
17
18 while (t--)
19 {
20 scanf("%s%s", str, ch);
21 n = strlen(str);
22 m = strlen(ch);
23
24 for (int i = 0; i < n; i++)
25 {
26 for (int j = 0; j < m; j++)
27 {
28 if (str[i] == ch[j])
29 {
30 dp[i + 1][j + 1] = dp[i][j] + 1;
31 }
32 else dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1]);
33 }
34 }
35
36 printf("%d\n", dp[n][m]);
37
38 }
39
40 return 0;
41 }

  如果,仅仅想得到结果,我们还可以将空间压缩一下。由于每次都之后用到i,i-1这两行数据,所以我们可以使用滚动数组。由于动态规划保证无后效性,所以我们完全可以使用一维数组。琢磨一下……

  相反如果我们想输出该序列呢,我们也完全可以加一个辅助数组flag[][].当str[i]
== ch[j],flag[i][j] = 0,如果dp[i - 1][j] > dp[i][j - 1],flag[i][j]
= 1,反之,flag[i][j] =
2;以此来记录起路径,最后从flag[n][m]开始往回找。

时间: 2024-10-20 01:24:57

序列最的问题之最长公共子序列LCS的相关文章

动态规划算法解最长公共子序列LCS问题

第一部分.什么是动态规划算法 ok,咱们先来了解下什么是动态规划算法. 动态规划一般也只能应用于有最优子结构的问题.最优子结构的意思是局部最优解能决定全局最优解(对有些问题这个要求并不能完全满足,故有时需要引入一定的近似).简单地说,问题能够分解成子问题来解决. 动态规划算法分以下4个步骤: 描述最优解的结构 递归定义最优解的值 按自底向上的方式计算最优解的值   //此3步构成动态规划解的基础. 由计算出的结果构造一个最优解.   //此步如果只要求计算最优解的值时,可省略. 好,接下来,咱们

求三个字符串的最长公共子序列LCS(A,B,C)

LCS(A,B,C)!=LCS(A,LCS(B,C)) 反例: abcd abcde abced LCS(B,C)求出来可能是abce或者abcd dp[i][j][k]表示A[0...i],B[0...j],C[0...k]的LCS 转移方程: if (a[i]==b[j]&&b[j]==c[k]) dp[i][j][k]=dp[i-1][j-1][k-1]+1; else dp[i][j][k]=max(max(dp[i][j][k], dp[i-1][j][k]), max(dp[i

[2016-05-09][51nod][1006 最长公共子序列Lcs]

时间:2016-05-09 21:12:54 星期一 题目编号:[2016-05-09][51nod][1006 最长公共子序列Lcs] 题目大意:[2016-05-09][51nod][1006 最长公共子序列Lcs].md 分析:动态规划 dp[i][j] 表示字符串A以第i个位置 ,字符串B以第j个位置的最长公共子序列的长度 dp[i][j] = dp[i - 1][j - 1] + 1 if a[i] == a[j] else dp[i][j] == max(dp[i - 1][j] ,

1006 最长公共子序列Lcs

1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列. Input 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) Output 输出最长的子序列,如果有多个,随意输出1个. Input示例 abcicba abdkscab Outpu

POJ 1458 Common Subsequence(最长公共子序列LCS)

POJ1458 Common Subsequence(最长公共子序列LCS) http://poj.org/problem?id=1458 题意: 给你两个字符串, 要你求出两个字符串的最长公共子序列长度. 分析: 本题不用输出子序列,非常easy,直接处理就可以. 首先令dp[i][j]==x表示A串的前i个字符和B串的前j个字符的最长公共子序列长度为x. 初始化: dp全为0. 状态转移: IfA[i]==B[j] then dp[i][j]= dp[i-1][j-1]+1 else dp[

51nod 1006 最长公共子序列Lcs(dp+string,无标记数组实现)

1006 最长公共子序列Lcs 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 取消关注 给出两个字符串A B,求A与B的最长公共子序列(子序列不要求是连续的). 比如两个串为: abcicba abdkscab ab是两个串的子序列,abc也是,abca也是,其中abca是这两个字符串最长的子序列. Input 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) Output 输出最长的子序列,如果有多个,随意输出1个. Input示

编程算法 - 最长公共子序列(LCS) 代码(C)

最长公共子序列(LCS) 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 给定两个字符串s,t, 求出这两个字符串最长的公共子序列的长度. 字符串的子序列并一定要连续, 能够包含间隔. 即最长公共子序列问题(LCS, Longest Common Subsequence) 使用动态规划, 假设字符相等, 两个字符串就依次递增一位, 一直到字符串的结尾. 代码: /* * main.cpp * * Created on: 2014.7.17

动态规划-最长公共子序列LCS

0 问题 给定两个字符串,求最长公共子序列LCS. 也就是说两个字符串中都有的部分,或者理解为,两个字符串同时都删除字符串中的某些字符,使得最终的两个字符串,相等,且是最长的. 1 分析 假设两个str1,str2字符串,已经知道了最长公共子序列长度为L 那么,当在str1和str2,两个的尾部,同时添加一个相同的字符,比如a,那么新的str1,和str2的最长公共子序列长度就是L+1 当str1后面添加一个字符,str2不添加,那么最长公共子序列长度为L 反之,str1不添加,str2添加,那

动态规划之最长公共子序列(LCS)

tips : 本文内容是参考了很多著名博客和自己的思考得出的,如有不当欢迎拍砖. 先简单说一下动态规划 通俗地说:动态规划就是将一个可以划分为子问题的问题进行递归求解,不过动态规划将大量的中间结果保存起来, 不管它们是否会用得到,从而在后面的递归求解过程中可以快速求解.由此可以看得出来动态规划是一个以牺牲空间 为代价换取时间的算法. 对于最长公共子序列的题目不用多说,现在来分析一下LCS的动态规划解决思路: 一.首先先观察问题是否符合动态规划最明显的两个特征:最优子结构和重叠子问题 方便起见,以