Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
题目描述
给定两个长度分别为 N 和 M 的字符串 A 和 B,求既是 A 的子序列又是 B 的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 N 和 M。
第二行包含一个长度为 N 的字符串,表示字符串 A。
第三行包含一个长度为 M 的字符串,表示字符串 B。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N,M≤1000
输入样例:
4 5
acbd
abedc
输出样例:
3
思路
我们通过题目可以很容易发现这是一道动态规划的问题,那动态规划的问题我们总结过可以使用状态表示f[i,j]和状态计算两个角度进行思考。
状态表示f[i, j]
- 集合:数组f[i, j]代表了一个集合,这个集合表示所有在第一个序列的前i个字母中出现,且在第二个序列的前j个子母中出现的子序列
- 属性:集合每个属性代表的含义是当前状态的最大值
状态计算
可以把f[i, j]划分为多个状态
1、不取a[i]并且不取b[i],对应的集合表达式:f[i -1, j - 1]
2、取a[i]并且不取b[i],对应的集合表达式:f[i -1, j ]
3、不取a[i]并且取b[i],对应的集合表达式:f[i, j - 1]
4、取a[i]并且取b[i],对应的集合表达式:f[i -1, j - 1] + 1
代码
#include <iostream>
using namespace std;
const int N = 1010;
char a[N],b[N];
int f[N][N];
int n ,m;
int main()
{
cin >> n >> m;
scanf("%s",a + 1);
scanf("%s",b + 1);
for(int i = 1;i <= n;i ++)
{
for(int j = 1;j <= m;j ++)
{
f[i][j] = max(f[i - 1][j], f[i][j - 1]);
if(a[i] == b[j]) f[i][j] = max(f[i][j], f[i - 1][j - 1] + 1);
}
}
cout << f[n][m] << endl;
return 0;
}
\