打印路径 递归是个好方法 从哪来回哪去
#include<iostream>
#include<string>
#include<vector>
using namespace std;
string s1 = "ABCDDEAD";
string s2 = "BBDCCDEA";
int len;
//求s1 与 s2的最长公共子序列
int LIS(vector<vector<int> > v, vector<vector<int> >& t){
s1.insert(0," ");
s2.insert(0," ");
int len1 = s1.size();
int len2 = s2.size();
//下标从1开始 因为计算中涉及到下标-1 避免数组越界
for(int i = 1; i < len1; i ++){
for(int j = 1; j < len2; j ++){
if(s1[i] == s2[j]){
v[i][j] = 1 + v[i-1][j-1];
t[i][j] = 1;
}
else if(v[i-1][j] >= v[i][j-1]){
v[i][j] = v[i-1][j];
t[i][j] = 2;
}
else{
v[i][j] = v[i][j-1];
t[i][j] = 3;
}
}
}
for(int i = 1; i < len1; i ++){
for(int j = 1; j < len2; j ++)
cout << t[i][j];
cout << endl;
}
return v[len1-1][len2-1];
}
void printLCS(int i,int j,vector<vector<int> > t){
if(i == 0 || j == 0)
return;
if(t[i][j] == 1){
printLCS(i-1,j-1,t);
cout << s1[i];
}
//从哪里走下来的从哪里退回去
else if(t[i][j] == 2)
printLCS(i-1,j,t);
else
printLCS(i,j-1,t);
}
int main()
{
vector<vector<int> > v(s1.size()+1,vector<int>(s2.size()+1,0));
vector<vector<int> > t(s1.size()+1,vector<int>(s2.size()+1,0));
int res = LIS(v,t);
printLCS(s1.size()-1,s2.size()-1,t);
cout << endl << res << endl;
}
s1[i] == s2[j] v[i][j] = 1 + v[i-1][j-1] 如果子问题的结尾相等 当前解为 1 + 两个串各退一步
s1[i] != s2[j] v[i][j] = max(v[i-1][j],v[i][j-1]); 如果子问题的结尾不相等 当前解为两个串各退一步的较大值
其中t数组用来 记录问题的路径