leetcode1143--最长公共子序列LCS

题目来源:https://leetcode-cn.com/problems/longest-common-subsequence/
最长公共子序列
给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。

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

若这两个字符串没有公共子序列,则返回 0。

示例 1:

输入:text1 = “abcde”, text2 = “ace”
输出:3
解释:最长公共子序列是 “ace”,它的长度为 3。
示例 2:

输入:text1 = “abc”, text2 = “abc”
输出:3
解释:最长公共子序列是 “abc”,它的长度为 3。
示例 3:

输入:text1 = “abc”, text2 = “def”
输出:0
解释:两个字符串没有公共子序列,返回 0。

上面是leetcode上的原题,要求是输出子序列的长度即可,我下面的代码是求出了子序列的字符串。

//LCS最长公共子序列
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <list>
using namespace std;

//暴力法(深搜)
list<char> dfs(string str1, string str2) {
	list<char> ans;
	int len1 = str1.length();
	int len2 = str2.length();
	for (int i = 0; i < len1; i++) {
		list<char> tmp_ans;
		for (int j = 0; j < len2; j++) {
			if (str1.at(i) == str2.at(j)) {
				tmp_ans.push_back(str1[i]);
				tmp_ans.splice(std::end(tmp_ans), dfs(str1.substr(i + 1), str2.substr(j + 1)));
			}
		}
		if (tmp_ans.size() > ans.size()) {
			ans.assign(tmp_ans.begin(), tmp_ans.end());
		}
	}
	return ans;
}

//动规
string LCS_dp(string str1, string str2) {
	int len1 = str1.length();
	int len2 = str2.length();
	vector< vector<string> > vector_dp;//dp二维数组
	for (int i = 0; i <= len2; i++) {
		vector<string> v(len1 + 1, "");
		vector_dp.push_back(v);
	}
	//初始化第一行
	for (int j = 1; j <= len1; j++) {
		if (!vector_dp[1][j - 1].empty()) {//如果前一个不为空,就等于上一次的结果
			vector_dp[1][j] = vector_dp[1][j - 1];
		}
		else if (str1[j - 1] == str2[0]) {
			vector_dp[1][j] = str2[0];
		}
		else {
			vector_dp[1][j] = "";
		}
	}
	//初始化第一列
	for (int i = 1; i <= len2; i++) {
		if (!vector_dp[i - 1][1].empty()) {//如果前一个不为空,就等于上一次的结果
			vector_dp[i][1] = vector_dp[i - 1][1];
		}
		else if (str2[i - 1] == str1[0]) {
			vector_dp[i][1] = str1[0];
		}
		else {
			vector_dp[i][1] = "";
		}
	}
	//计算其他
	for (int row = 2; row <= len2; row++) {
		for (int col = 2; col <= len1; col++) {
			if (str1[col - 1] != str2[row - 1]) {//如果当前字符不相等,就取历史上最大的(左或者上)
				if (vector_dp[row - 1][col].length() > vector_dp[row][col - 1].length())
					vector_dp[row][col] = vector_dp[row - 1][col];
				else
					vector_dp[row][col] = vector_dp[row][col - 1];
			}
			else {//如果当前字符相等,就在左上角的基础上加上当前的字符
				vector_dp[row][col] = vector_dp[row - 1][col - 1] + str1[col - 1];
			}
		}
	}
	return vector_dp[len2][len1];
}

int main() {
	string str1, str2;
	cin >> str1 >> str2;

	list<char> l = dfs(str1, str2);
	for (char ch : l) {
		cout << ch;
	}
	cout << endl;

	cout << LCS_dp(str1, str2) << endl;
	return 0;
}

/*
AB34C
A1BC2D
*/

附上leetcode上AC的代码,虽然性能很差

class Solution {
public:
    int longestCommonSubsequence(string text1, string text2) {
    int len1 = text1.length();
	int len2 = text2.length();
	vector< vector<string> > vector_dp;//dp二维数组
	for (int i = 0; i <= len2; i++) {
		vector<string> v(len1 + 1, "");
		vector_dp.push_back(v);
	}
	//初始化第一行
	for (int j = 1; j <= len1; j++) {
		if (!vector_dp[1][j - 1].empty()) {//如果前一个不为空,就等于上一次的结果
			vector_dp[1][j] = vector_dp[1][j - 1];
		}
		else if (text1[j - 1] == text2[0]) {
			vector_dp[1][j] = text2[0];
		}
		else {
			vector_dp[1][j] = "";
		}
	}
	//初始化第一列
	for (int i = 1; i <= len2; i++) {
		if (!vector_dp[i - 1][1].empty()) {//如果前一个不为空,就等于上一次的结果
			vector_dp[i][1] = vector_dp[i - 1][1];
		}
		else if (text2[i - 1] == text1[0]) {
			vector_dp[i][1] = text1[0];
		}
		else {
			vector_dp[i][1] = "";
		}
	}
	//计算其他
	for (int row = 2; row <= len2; row++) {
		for (int col = 2; col <= len1; col++) {
			if (text1[col - 1] != text2[row - 1]) {//如果当前字符不相等,就取历史上最大的(左或者上)
				if (vector_dp[row - 1][col].length() > vector_dp[row][col - 1].length()) 
					vector_dp[row][col] = vector_dp[row - 1][col];
				else 
					vector_dp[row][col] = vector_dp[row][col - 1];
			}
			else {//如果当前字符相等,就在左上角的基础上加上当前的字符
				vector_dp[row][col] = vector_dp[row - 1][col - 1] + text1[col - 1];
			}
		}
	}
	return vector_dp[len2][len1].length();
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值