题目来源: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();
}
};