题目描述
给定两个长度分别为 N和 M的字符串 A和 B,求既是 A的子序列又是 B的子序列的字符串长度最长是多少。
输入格式
第一行包含两个整数 N 和 M。
第二行包含一个长度为 N的字符串,表示字符串 A。
第三行包含一个长度为 M 的字符串,表示字符串 B。
字符串均由小写字母构成。
输出格式
输出一个整数,表示最大长度。
数据范围
1≤N,M≤1000
样例
输入样例
4 5
acbd
abedc
输出样例
3
代码
#include <bits/stdc++.h>
using namespace std;
int n,m;
char a[1001],b[1001];
int dp[1001][1001];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int j=1;j<=m;j++)
cin>>b[j];
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i]!=b[j]) dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
else dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
}
}
cout<<dp[n][m]<<endl;
return 0;
}
思路
1、dp[i][j]含义:存放既在a字符串前i个又在b字符串前j个中的子序列最大长度;
2、递推公式:dp[i][j]=max(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+1);
①按最长公共子序列是否包含a[i],b[j]分为四种情况:即00,01,10,11,取长度最大即为所求;
②而dp[i-1][j]包含了01的情况,dp[i][j-1]包含了10的情况;
③dp[i-1][j-1]包含在dp[i-1][j],dp[i][j-1]这两种情况中,所以就变成了上述递推公式;
3、初始化:dp全部初始化为0;
4、for循环顺序:先遍历a再遍历b,或先遍历b再遍历a都可以;
5、打印dp数组,验证正确性。