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();
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章