/***************************************************************************
*description:最长公共子序列
* 给定两个字符串str1和str2,返回两个字符串的最长公共子序列
* 如:str1=“1A2C3D4B56” str2=“B1D23CA45B6A”
* 返回“123456”或者“12C4B6”都可以
*description:最长公共子序列
* 给定两个字符串str1和str2,返回两个字符串的最长公共子序列
* 如:str1=“1A2C3D4B56” str2=“B1D23CA45B6A”
* 返回“123456”或者“12C4B6”都可以
**************************************************************************/
#include<iostream>
#include<vector>
#include<string>
using namespace std;
//方法:时间复杂度O(M*N),空间复杂度O(M*N)
//经典动态规划问题,数组dp[M][N]
//dp[i][j]代表str1[0...i]与str2[0...j]的最大公共子序列长度
//dp[0][j]和dp[i][0]先求得
//然后从左到右,从上到下:dp[i][j]取下面三个中的最大值:
// 1.dp[i-1][j]
// 2.dp[i][j-1]
// 3.dp[i-1][j-1]+1 当str1[i]==str2[j]
//得到dp之后,从右下角往回找,对于dp[i][j]:
// 1.=dp[i][j-1]:找dp[i][j-1]
// 2.=dp[i-1][j]:找dp[i-1][j]
// 3.=dp[i-1][j-1]:res加入str1[i]
string longestSharedSubSequence(string str1, string str2)
{
string res;
int M = str1.size();
int N = str2.size();
if (M == 0 || N == 0)
return res;
vector<vector<int>> dp(M, N);
for (int i = 0; i < M; i++)
{
dp[i][0] = 0;
if (str1[i] == str2[0])
{
for (int j = i; j < M; j++)
dp[j][0] = 1;
break;
}
}
for (int i = 0; i < N; i++)
{
dp[0][i] = 0;
if (str1[0] == str2[i])
{
for (int j = i; j < N; j++)
dp[0][j] = 1;
break;
}
}
for(int i = 1; i < M; i++)
{
for (int j = 1; j < N; j++)
{
dp[i][j] = dp[i-1][j] > dp[i][j-1] ? dp[i-1][j] : dp[i][j-1];
if (str1[i] == str2[j])
dp[i][j] = dp[i][j]+1 > dp[i-1][j-1] ? dp[i][j]+1 : dp[i-1][j-1];
}
}
int len = dp[M-1][N-1];
int i = M-1;int j=N-1;
while(len > 0)
{
if (i > 0 && dp[i][j] == dp[i-1][j])
i--;
else if(j > 0 && dp[i][j] == dp[i][j-1])
j--;
else
{
res.push_back(str1[i]);
--len;
i--;
j--;
}
}
return res;
}
int main_07()
{
string str1 = "1A2C3D4B56";
string str2 = "B1D23CA45B6A";
cout << longestSharedSubSequence(str1, str2);
return 0;
}