最长公共子序列和最长公共子串——C++
一、给定两个字符串S1和S2,求两个字符串的最长公共子序列的长度。 输入样例 ABCD AEBD 输出样例 3 解释 S1和S2的最长公共子序列为ABD,长度为3
思路 动态规划 LCS(m,n)表示S1[0…m)和S2[0…n)的最长公共子序列的长度 S1[m-1] == S2[n-1]: LCS(m, n) = 1 + LCS(m - 1, n - 1); S1[m-1] != S2[n-1]: LCS(m, n) = max(LCS(m - 1, n), LCS(m, n - 1))。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Solution{
public:
int max(int x, int y)
{
if (x <= y)
return x;
else
{
return y;
}
}
//找出最长公共子序列的长度
int lengthOflongestCommonSequence(string& str1, string& str2){
int m = str1.length(), n = str2.length();
if (m == 0 || n == 0)
return 0;
dp = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i < m + 1; ++i){
for (int j = 1; j < n + 1; ++j){
if (str1[i - 1] == str2[j - 1])
dp[i][j] = dp[i - 1][j - 1] + 1;
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
}
return dp[m][n];
}
// 找出所有的最长公共子序列
// 这里形参lcs_str不可以为引用,这里需要每次调用lcs_str都重新生成一个对象
void PrintAllLCS(string& str1, string& str2, int i, int j, string lcs_str){
//i, j为str1和str2的长度
while (i > 0 && j > 0){
if (str1[i - 1] == str2[j - 1]){
lcs_str = str1[i - 1] + lcs_str;
--i;
--j;
}
else{
if (dp[i - 1][j] > dp[i][j - 1]) //str1向前走
--i;
else if (dp[i - 1][j] < dp[i][j - 1]) //str2向前走
--j;
//str1和2向前均为LCS的元素
else{
PrintAllLCS(str1, str2, i - 1, j, lcs_str);
PrintAllLCS(str1, str2, i, j - 1, lcs_str);
return;
}
}
}
all_lcs.insert(lcs_str);
}
vector<vector<int>> dp;
set<string> all_lcs;
};
int main()
{
string s1 = "abcfbc";
string s2 = "abfcab";
Solution fir;
string lcs_str;
int res = fir.lengthOflongestCommonSequence(s1, s2);
cout << res << endl;
fir.PrintAllLCS(s1, s2, s1.length(), s2.length(), lcs_str);
set<string>::iterator iter = fir.all_lcs.begin();
while (iter != fir.all_lcs.end()) {
cout << *iter++ << endl;
}
return 0;
}
/*
4
abcb
abfb
abfc
*/
二、求两个字符串的最长公共子串,要求子串连续 输入例子: bab caba 输出例子: 2 思路 动态规划 dp(m,n)表示S1[0…m)和S2[0…n)的最长公共子串的长度 当S1[m-1]==S2[n-1]: dp(m,n)=1+dp(m−1,n−1); 当S1[m-1]!=S2[n-1]: dp(m,n) = 0。
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class Solution {
public:
//输出最长公共子串的长度
int lengthOflongestCommonSubstring(string& str1, string& str2){
int m = str1.size(), n = str2.size();
int res = 0;
vector<vector<int> > dp(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; ++i){
for (int j = 1; j <= n; ++j){
if (str1[i - 1] == str2[j - 1])
dp[i][j] = dp[i - 1][j - 1] + 1;
else
dp[i][j] = 0;
if (res < dp[i][j])
res = dp[i][j];
}
}
return res;
}
//输出最长公共子串
string LCS(string str1, string str2) {
int m = str1.size();
int n = str2.size();
string res = "-1";
int len = 0;
int pos = 0;
vector<vector<int>>dp(m + 1, vector<int>(n + 1, 0));
for (int i = 1; i <= m; i++)
{
for (int j = 1; j <= n; j++)
{
if (str1[i - 1] == str2[j - 1])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
}
else
{
dp[i][j] = 0;
}
if (len < dp[i][j])
{
len = dp[i][j];
pos = i;
}
}
}
if (len == 0)
{
return res;
}
res = str1.substr(pos - len, len);
return res;
}
};
int main()
{
}
