题目可以看力扣上的这个:https://leetcode.cn/problems/qJnOS7/
dp求最长子序列的问题,过长的字符串处理不了,因为dp过程中要用到二维数组,二维数组定义不能过大。
下面代码我做了扩展,增加了输出最长子序列字符串的部分。总得来说目前看到的输出所求字符串的做法有两种:
一:遍历过程中直接用string的二维数组记录。
二:回溯法:先遍历求出长度,过程中记录获得数值的路径。后续再遍历路径数组求出最长子序列。
法一代码
//求最长公共子序列,遍历过程中记录公共字符串
#include<iostream>
#include<string>
using namespace std;
string STR[1005][1005];
int main()
{
string str1, str2;
cin >> str1 >> str2;
for (int i = 0; i < str1.size(); i++)
{
for (int j = 0; j < str2.size(); j++)
{
if (str1[i] == str2[j])
{
STR[i + 1][j + 1] = STR[i][j] + str2[j];//str数组下标从0开始,为避免0-1越界情况,向后延伸(不用STR[i][j]=STR[i-1][j-1]+1)
}
else
{
if (STR[i][j + 1].size() > STR[i + 1][j].size())
STR[i + 1][j + 1] = STR[i][j + 1];
else
STR[i + 1][j + 1] = STR[i + 1][j];
}
}
}
cout << STR[str1.size()][str2.size()].size() << '\n';
cout << STR[str1.size()][str2.size()]<< '\n';
return 0;
}
法二代码
对于路径数组c,规定
c=1记录数值从对角线方向传来,且值改变加1了(即d[i + 1][j + 1] = d[i][j] + 1)
c=2记录数值从左传来(d[i + 1][j + 1] = d[i][j + 1])
c=3记录数值从上传来(d[i + 1][j + 1] = d[i + 1][j])
且当左,上两个方向数值相等时,规定数值由从上传来得到
//求最长公共子序列,先确定最大长度,再回溯得到所求字符串
#include<iostream>
#include<string>
#include<algorithm>
#include<stack>
using namespace std;
int d[10005][10005];
int c[10005][10005];
stack<char> s;
int main()
{
string str1, str2;
cin >> str1 >> str2;
for (int i = 0; i < str1.size(); i++)
for (int j = 0; j < str2.size(); j++)//str数组下标从0开始,但d数组需要从前方传递,在0处-1会越界,因此后延(从1行1列开始记录数据)
{
if (str1[i] == str2[j])
{
d[i + 1][j + 1] = d[i][j] + 1;
c[i + 1][j + 1] = 1;
}
else
{
if (d[i + 1][j] >= d[i][j + 1])//当左,上两个方向数值相等时,规定数值由从上传来得到
{
d[i + 1][j + 1] = d[i + 1][j];
c[i + 1][j + 1] = 3;
}
else
{
d[i + 1][j + 1] = d[i][j + 1];
c[i + 1][j + 1] = 2;
}
}
}
cout << d[str1.size()][str2.size()] << '\n';
int i = str1.size(), j = str2.size();
while (i > 0 && j > 0)//回溯路径数组c,找出最长子序列组成部分
{
if (c[i][j] == 1)//根据栈先进后出的特点,取它记录记录路径,后续输出即可得到正序路径
{
s.push(str1[i - 1]);//因为前面遍历记录路径时,记录数据后延从1开始,和字符串的对应要对应-1
i--;//例如:0行0列在d,c数组中是初始化未记录数据的地方,但str1[0]='a',str2[0]='a'
j--;
}
else if (c[i][j] == 2)
i--;
else
j--;
}
while (s.size())
{
cout << s.top();
s.pop();
}
cout << '\n';
return 0;
}