最长公共子序列

Leetcode 题解 - 动态规划

ぃ、小莉子 提交于 2020-01-28 11:13:07
递归和动态规划都是将原问题拆成多个子问题然后求解,他们之间最本质的区别是,动态规划保存了子问题的解,避免重复计算。 斐波那契数列 Leetcode-70. 爬楼梯 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数。 示例 1: 输入: 2 输出: 2 解释: 有两种方法可以爬到楼顶。 1. 1 阶 + 1 阶 2. 2 阶 示例 2: 输入: 3 输出: 3 解释: 有三种方法可以爬到楼顶。 1. 1 阶 + 1 阶 + 1 阶 2. 1 阶 + 2 阶 3. 2 阶 + 1 阶 解法: Java 定义一个数组 dp 存储上楼梯的方法数(为了方便讨论,数组下标从 1 开始),dp[i] 表示走到第 i 个楼梯的方法数目。 第 i 个楼梯可以从第 i-1 和 i-2 个楼梯再走一步到达,走到第 i 个楼梯的方法数为走到第 i-1 和第 i-2 个楼梯的方法数之和。 考虑到 dp[i] 只与 dp[i - 1] 和 dp[i - 2] 有关,因此可以只用两个变量来存储 dp[i - 1] 和 dp[i - 2],使得原来的 O(N) 空间复杂度优化为 O(1) 复杂度。 class Solution { public int climbStairs ( int n ) { if ( n

1006 最长公共子序列Lcs

荒凉一梦 提交于 2020-01-27 11:05:06
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 Output 示例 abca import java.util.Scanner; import java.util.Stack; public class Main { static int dp[][]; static char a[]; static char b[]; static void LCS(int n,int m){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(a[i-1]==b[j-1])dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=Math.max(dp[i][j-1], dp[i-1][j]); } } } public static void

C语言 · 最长公共子序列 · 最长字符序列

徘徊边缘 提交于 2020-01-25 05:18:38
算法提高篇有两个此类题目: 算法提高 最长字符序列 时间限制:1.0s 内存限制:256.0MB   最长字符序列 问题描述   设x(i), y(i), z(i)表示单个字符,则X={x(1)x(2)……x(m)},Y={y(1)y(2)……y(n)},Z={z(1)z(2)……z(k)},我们称其为字符序列,其中m,n和k分别是字符序列X,Y,Z的长度,括号()中的数字被称作字符序列的下标。   如果存在一个严格递增而且长度大于0的下标序列{i1,i2……ik},使得对所有的j=1,2,……k,有x(ij)=z(j),那么我们称Z是X的字符子序列。而且,如果Z既是X的字符子序列又是Y的字符子序列,那么我们称Z为X和Y的公共字符序列。   在我们今天的问题中,我们希望计算两个给定字符序列X和Y的最大长度的公共字符序列,这里我们只要求输出这个最大长度公共子序列对应的长度值。   举例来说,字符序列X=abcd,Y=acde,那么它们的最大长度为3,相应的公共字符序列为acd。 输入格式   输入一行,用空格隔开的两个字符串 输出格式   输出这两个字符序列对应的最大长度公共字符序列的长度值 样例输入 aAbB aabb 样例输出 2 数据规模和约定   输入字符串长度最长为100,区分大小写。 算法提高 最长公共子序列 时间限制:1.0s 内存限制:256.0MB 问题描述  

最长公共子序列问题(LCS)

守給你的承諾、 提交于 2020-01-21 15:45:13
题目链接 给定两个长度分别为N和M的字符串A和B,求既是A的子序列又是B的子序列的字符串长度最长是多少。 输入格式 第一行包含两个整数N和M。 第二行包含一个长度为N的字符串,表示字符串A。 第三行包含一个长度为M的字符串,表示字符串B。 字符串均由小写字母构成。 输出格式 输出一个整数,表示最大长度。 数据范围 1≤N≤1000, 输入样例: 4 4 abcd becd 输出样例: 3(bcd) 解题思路 dp[i][j] := A1…Ai 和 B1…Bj对应的LCS的长度. 由此,A1…Ai 和 B1…Bj对应的公共子序列可能是 当A(i+1) = B(j+1)时,在A1…Ai 和 B1…Bj的的公共子序列末尾追加上A(i+1) A1…A(i+1) 和 B1…Bj 的公共子序列 A1…A(i+1) 和 B1…B(j+1)的公共子序列 三者中的某一个,有如下的递推关系成立 dp[i+1][j+1] = max(dp[i][j] + 1, dp[i+1][j], dp[i][j+1]) // A(i+1) = B(j+1) p[i+1][j+1] = max(dp[i+1][j], dp[i][j+1]) // A(i+1) != B(j+1) 时间复杂度:O(N*M) , dp[n][m] 即为LCS的长度 用二维矩阵模拟题目的例子如下: dp数组的变化过程 import

回文串(最长公共子序列)

£可爱£侵袭症+ 提交于 2020-01-17 21:21:44
一个字符串如果从左往右读和从右往左读都一样,那么这个字符串是一个回文串。例如:"abcba","abccba"。 蒜头君想通过添加字符把一个非回文字符串变成回文串。例如:"trit",可以添加一个i变成回文串"tirit"。 请你用程序计算出,对于一个给定的字符串,最少需要添加几个字符,才能变成回文串。 输入格式 输入一个长度为n(1≤n≤3000)的字符串。(字符串只包含字母) 输出格式 输出最少需要添加的字符个数,占一行。 样例输入 trit 样例输出 1 把回文串的顺序倒转后,与原串是一样的。 那么我们只要把给定的字符串顺序倒转与原串求最长公共子序列,再用字符串总长度减去最长公共子序列的长度就是相差的字符个数,也就是答案。 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <string> 5 #include <math.h> 6 #include <algorithm> 7 #include <vector> 8 #include <stack> 9 #include <queue> 10 #include <set> 11 #include <map> 12 #include <sstream> 13 #include <ctime> 14 const int INF

最长公共子序列

我们两清 提交于 2020-01-17 15:28:13
动态规划+优化,双100% 思路 1、考虑从后往前推导,随着字符串的变长,两个字符串的最后一个字符相同或者不同,对最长公共子序列的长度影响。 2、使用arr[i][j]表示text1的前i个字符和text2的前j个字符的最长公共子序列长度,得到以下状态转移方程:    若text1的第i个字符和text2的第j个字符相同,则      arr[i][j] = arr[i - 1][j - 1] + 1;    否则      arr[i][j] = Math.max(arr[i][j - 1], arr[i - 1][j]); 3、考虑二维数组每次循环的时候只有最后一行数据才有作用,前面已经计算过的已无效,可以优化成一维数组。 4、考虑边界问题,可以在两个字符串前面追加“#”,防止边界越界,不要判断边界是否大于0,提升效率。 class Solution { public int longestCommonSubsequence(String text1, String text2) { int m = text1.length(); int n = text2.length(); m++; n++; int[] arr = new int[n]; char[] arr1 = ("#" + text1).toCharArray(); char[] arr2 = ("#" +

Acwing897 最长公共子序列

ε祈祈猫儿з 提交于 2020-01-16 09:41:05
题目大意:求两个字符串的最长公共子序列的长度。 分析:这是一个典型的dp入门题,LCS。 代码: #include<bits/stdc++.h> using namespace std; const int maxn = 1e3+7; char a[maxn],b[maxn]; int dp[maxn][maxn]; void Dp() { int n = strlen(a); int m = strlen(b); for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (a[i] == b[j]) dp[i + 1][j + 1] = dp[i][j] + 1; else dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i + 1][j]); } } } int main() { int n, m; cin >> n >> m; cin >> a >> b; Dp(); cout << dp[n][m] << endl; return 0; } 来源: https://www.cnblogs.com/SwiftAC/p/12199608.html

求最长公共子序列(子序列在原串中可以不连续)

送分小仙女□ 提交于 2020-01-15 21:20:27
1. 问题描述: 最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。 2. 用途: 最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的“相似度”,即它们的雷同程度,从而能够用来辨别抄袭。对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,这种方法判断修改的部分,往往十分准确。简而言之,百度知道、百度百科都用得上。 3. 动态规划解法: 动态规划的方法求序列X,Y的最长公共子序列 以两个序列 X、Y 为例子: 设有二维数组 f[i][j] 表示 X 的 i 位和 Y 的 j 位之前的最长公共子序列的长度,则有: f[1][1] = same(1,1); f[i][j] = max{f[i-1][j -1] + same(i,j),f[i-1,j],f[i,j-1]} 其中,same(a,b)当 X 的第 a 位与 Y 的第 b 位完全相同时为“1”,否则为“0”。 最后f[lenX][lenY]即为最长公共子序列的值。 该算法的空间、时间复杂度均为O(n^2),经过优化后,空间复杂度可为O(n)。 4. 代码实现: #include

动态规划之最长公共子序列问题

强颜欢笑 提交于 2020-01-15 21:08:26
由最长公共子序列问题的最优子结构性质建立子问题最优值的递归关系。 用c[i][j]记录序列X和Y的最长公共子序列的长度,其中, Xi={x1,x2,…,xi};Yj={y1,y2,…,yj}。 当i=0或j=0时,空序列是Xi和Yj的最长公共子序列。 故此时C[i][j]=0。其他情况下,由最优子结构性质可建立递归关系如下: void LCSLength( int m,int n,char *x,char *y,int **c,int **b ) //c[i][j] 记录Xi和Yj 的最长公共子序列长, { int i,j; //b[i][j] 记录c[i][j]是由哪个子问题得到的。 for (i = 0; i <= m; i++) c[i][0] = 0; //第一列 for (i = 0; i <= n; i++) c[0][i] = 0; //第一行 for (i = 1; i <= m; i++) for (j = 1; j <= n; j++) { if (x[i]==y[j]) { c[i][j]=c[i-1][j-1]+1; b[i][j]=1;} //if 左上角 else if (c[i-1][j]>=c[i][j-1]) { c[i][j]=c[i-1][j]; b[i][j]=2;} //else if 上面 else { c[i][j]=c[i][j-1]

最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

六眼飞鱼酱① 提交于 2020-01-15 20:53:16
最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。 而最长公共子串(要求连续)和最长公共子序列是不同的. 最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的"相似度",即它们的雷同程度,从而能够用来辨别抄袭。对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,这种方法判断修改的部分,往往十分准确。 动态规划法 经常会遇到复杂问题不能简单地分解成几个子问题,而会分解出一系列的子问题。简单地采用把大问题分解成子问题,并综合子问题的解导出大问题的解的方法,问题求解耗时会按问题规模呈幂级数增加。为了节约重复求相同子问题的时间,引入一个数组,不管它们是否对最终解有用,把所有子问题的解存于该数组中,这就是动态规划法所采用的基本方法。 算法 动态规划的一个计算两个序列的最长公共子序列的方法如下: 以两个序列 X、Y 为例子: 设有二维 数组 f[i,j] 表示 X 的 i 位和 Y 的 j 位之前的最长公共子序列的长度,则有: f[1][1] = same(1,1); f[i,j] = max{f[i-1][j -1] + same(i,j),f[i-1,j],f[i,j-1]}