版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zpalyq110/article/details/79994001
解题思路:
求两个字符串的最长公共子序列,这是一道经典的动态规划的问题,大致需要两个过程:
假设两个字符串的长度分别为m、n;
- 建立表格:c[][]数组记录字符相等数,遍历m*n次,判断字符是否一样,相等max(left,top)+1,不相等取max(left,top);同时填充d[][]数组,记录的是路径的方向,以便后面回溯出最长公共子序列,0、1、2、3分别代表lefttop、top、left、left==top。
- 回溯公共子串:比较麻烦的情况就是多个解,需要定义一个全局变量来存放所有解,并且在分支前记录两个解的公共前缀。
代码:
#include <iostream>
#include<string>
#include<vector>
#include<set>
using namespace std;
set<string> setOfLCS;
int LCSlen(string str1, string str2, int **d) {
int len1 = str1.size();
int len2 = str2.size();
int **c = new int*[len1 + 1];//行数
for (int i = 0; i < len1 + 1; i++) {
c[i] = new int[len2 + 1];//列数
}
for (int i = 0; i < len1 + 1; i++)
c[i][0] = 0;
for (int i = 0; i < len2 + 1; i++)
c[0][i] = 0;
for (int i = 1; i < len1 + 1; i++)
{
for (int j = 1; j < len2 + 1; j++)
{
if (str1[i - 1] == str2[j - 1])//c的第i行元素对应str1的第i-1个元素
{
c[i][j] = c[i - 1][j - 1] + 1;
d[i][j] = 0; //方向 : lefttop
}
else if (c[i - 1][j] > c[i][j - 1])
{
c[i][j] = c[i - 1][j];
d[i][j] = 1; //方向 : top
}
else if (c[i - 1][j] < c[i][j - 1])
{
c[i][j] = c[i][j - 1];
d[i][j] = 2; //方向 : left
}
else
{
c[i][j] = c[i][j - 1];
d[i][j] = 3; //方向 :top==left
}
}
}
return c[len1][len2];
}
void PrintLCS(int **d, string str1, string lcs, int i, int j)
{
while (i >0 && j >0){
if (d[i][j] == 0)
{
string ss;
ss = str1[i - 1];
lcs.insert(0, ss);
i--;
j--;
}
else if (d[i][j] == 1)
i -- ;// top
else if(d[i][j] == 2)
j --; // left
else
{
PrintLCS(d, str1, lcs, i - 1, j);
PrintLCS(d, str1, lcs, i , j - 1);
return;
}
}
setOfLCS.insert(lcs);
}
int main() {
string str1, str2;
cout << "请输入第一个字符串:" << endl;
cin >> str1;
cout << "请输入第二个字符串:" << endl;
cin >> str2;
//str1 = "ABCBDAB";
//str2 = "BDCABA";
int len1 = str1.size();
int len2 = str2.size();
int **d = new int*[len1 + 1];//行数
for (int i = 0; i < len1 + 1; i++) {
d[i] = new int[len2 + 1];//列数
}
int len = LCSlen(str1, str2, d);
cout << "最长公共子序列的长度为:" << len << endl;
cout << "最长公共子序列为:" << endl;
string lcs;
PrintLCS(d, str1, lcs,len1, len2);
set<string>::iterator beg = setOfLCS.begin();
for (; beg != setOfLCS.end(); ++beg)
cout << *beg << endl;
system("pause");
return 0;
}