1143. 最长公共子序列_动态规划

1143. 最长公共子序列

1.题目描述

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。
例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。两个字符串的「公共子序列」是这两个字符串所共同拥有的子序列。

若这两个字符串没有公共子序列,则返回 0。
题目链接:https://leetcode-cn.com/problems/longest-common-subsequence/

2.思路

采用动态规划的策略,与最大上升子序列长度的动态规划解法不同的是,采用了二维的dp 数组(表格) 而非一维dp数组。
状态定义:
为了表示方便,先举例:

text1 = "abcd"
text2 = "ace"

dp table

\“”“a”“b”“c”“d”
“”00000
“a”01111
“c”01122
“e”01122

横轴、纵轴分别表示两个字符串的各个字符, 其中从第一列(行)表示空串的情况。

d p [ i ] [ j ] dp[i][j] dp[i][j]表示text2的前i个字符子串和text1的前j个字符字串的LCS(longest common string)长度。边界状态:当其中一个为空串时,其LCS值必为0。

状态转移方程:
d p [ i + 1 ] [ j + 1 ] = d p [ i ] [ j ] + 1   i f   t e x t 1 [ i + 1 ] = = t e x t 2 [ j + 1 ] dp[i+1][j+1] =dp[i][j]+1 \ if \ text1[i+1]==text2[j+1] dp[i+1][j+1]=dp[i][j]+1 if text1[i+1]==text2[j+1]
d p [ i + 1 ] [ j + 1 ] = m a x ( d p [ i ] [ j + 1 ] , d p [ i + 1 ] [ j ] ) i f   t e x t 1 [ i + 1 ]   ! = t e x t 2 [ j + 1 ] dp[i+1][j+1] =max(dp[i][j+1], dp[i+1][j]) if \ text1[i+1]\ != text2[j+1] dp[i+1][j+1]=max(dp[i][j+1],dp[i+1][j])if text1[i+1] !=text2[j+1]
简单的理解就是:在已知两个字符串的LCS的前提下,同时往两个字符串后添加一个字符,如果该两字符相等,则说明新的字符串对的LCS长度为 原LCS长度值加1。如果给两个字符不相等,向上、向左相邻的LCS值中两者较大值。向左(或向上)相邻的LCS值 等价于 在已知两个字符串的LCS值前提下,向其中一个字符串添加一个字母,那么新的LCS值就有两种可能,要么不变,要么加1。

3.代码

int longestCommonSubsequence(string text1, string text2) {
	if (text1.empty() || text2.empty())
		return 0;

	// 找出两个字符串长度
	int length_t1 = text1.size();
	int length_t2 = text2.size();

	// 定义 dp table
	vector<int> a(length_t2+1, 0);
	vector<vector<int>> dp(length_t1+1, a);

	// 填充 dp table
	for(int i = 1; i < length_t1+1; i++)
		for (int j = 1; j < length_t2 + 1; j++) {
			// 状态转移方程
			if (text2[j - 1] == text1[i - 1])
				dp[i][j] = dp[i - 1][j - 1] + 1;
			else {
				dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]);
			}
		}

	// dp table最后一个位置即为LCS值。
	int lcs = dp[length_t1][length_t2];
	return lcs;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值