#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<vector>
#include<set>
using namespace std;
//veca表用来记录最长子序列的长度值,vecb是用来输出路径的辅助表(可以不要)
int LCS_length(const string &str1, const string &str2,
vector<vector<int>> &veca, vector<vector<int>> &vecb) {
if (str1 == "" || str2 == "")
return 0;
for(int i=0;i<=str1.size();++i)
for (int j = 0; j <= str2.size(); ++j) {
if (i == 0 || j == 0)
veca[i][j] = 0;
else if (str1[i - 1] == str2[j - 1]) {
//同一个字母在string里的序号与在veca表里的序号不同
veca[i][j] = veca[i - 1][j - 1] + 1;
vecb[i][j] = 1;
}
else {
if (veca[i - 1][j] >= veca[i][j - 1]){
veca[i][j] = veca[i - 1][j];
vecb[i][j] = 2;
}
else{
veca[i][j] = veca[i][j - 1];
vecb[i][j] = 3;
}
}
}
return veca[str1.size()][str2.size()];
}
//输出一条路径,利用辅助二维数组
void printOneLCS(const vector<vector<int>> &vecb, const string &str1, int i, int j) {
if (i == 0 || j == 0)
return;
if (vecb[i][j] == 1) {
printOneLCS(vecb, str1, i - 1, j - 1);
cout << str1[i - 1];
}
else if(vecb[i][j] == 2)
printOneLCS(vecb, str1, i - 1, j);
else
printOneLCS(vecb, str1, i, j - 1);
}
//输出一条路径,不需要辅助二维数组,从右下角开始,去左上角方向。
//每次都比较左边与上边的数字,往较大的方向走,如果相等则默认向上走(也可以默认向左)
void printOneLCS2(const vector<vector<int>> &veca, const string &str1, const string &str2) {
string str;
int i=str1.size(), j=str2.size();
while (i > 0 && j > 0) {
if (str1[i - 1] == str2[j - 1]) {
str = str1[i - 1] + str;
--i;
--j;
}
else {
if (veca[i - 1][j] >= veca[i][j - 1])
--i;
else
--j;
}
}
cout << str << endl;
}
//输出所有路径,先压入set然后输出,以去除重复路径
set<string> allLCS;
void printAllLCS(const vector<vector<int>> &veca, const string &str1, const string &str2,
string str, int i, int j) {
while (i>0 && j>0)
{
if (str1[i - 1] == str2[j - 1]) {
str = str1[i - 1] + str;
--i;
--j;
}
else {
if (veca[i - 1][j] > veca[i][j - 1])
--i;
else if(veca[i - 1][j] < veca[i][j - 1])
--j;
else {
printAllLCS(veca, str1, str2, str, i - 1, j);
printAllLCS(veca, str1, str2, str, i, j - 1);
return;
}
}
}
//cout << str << endl;
allLCS.insert(str);
}
int main() {
string str1, str2;
//cin >> str1 >> str2;
str1 = "ABCBDAB";
str2 = "BDCABA";
vector<vector<int>> veca(str1.size() + 1, vector<int>(str2.size() + 1));
vector<vector<int>> vecb(str1.size() + 1, vector<int>(str2.size() + 1));
cout << LCS_length(str1,str2,veca,vecb) << endl;
printOneLCS(vecb, str1, str1.size(), str2.size()); cout << endl;
printOneLCS2(veca, str1, str2);
string str;
printAllLCS(veca, str1, str2, str, str1.size(), str2.size());
for (auto a : allLCS)
cout << a << endl;
return 0;
}
子串的区别就是必须连续。
因此,当str1[i-1] != str2[j-1]时,vec[i][j]=0。
int LCSchuan(vector<vector<int>> &vec, const string &str1, const string &str2) {
if (str1 == "" || str2 == "")
return 0;
int longest=0;
for (int i = 0; i <= str1.size(); ++i)
for (int j = 0; j <= str2.size(); ++j) {
if (i == 0 || j == 0)
vec[i][j] = 0;
else if (str1[i - 1] == str2[j - 1]) {
vec[i][j] = vec[i - 1][j - 1] + 1;
if (vec[i][j] > longest)
longest = vec[i][j];
}
else {
vec[i][j]=0;
}
}
return longest;
}
set<string> allLCSchuan;
void printAllLCSchuan(const vector<vector<int>> &vec, const string &str1, const string &str2, int longest) {
for (int i = 1; i <= str1.size(); ++i) {
for (int j = 1; j <= str2.size(); ++j) {
if (vec[i][j] == longest) {
string str;
for(int k=0;k<longest;++k)
str = str1[i - 1 - k] + str;
allLCSchuan.insert(str);
}
}
}
}