[动态规划]最长公共子序列(LCS)
题目描述
一个给定的子序列是在该序列中删去若干元素后得到的序列。例如,序列z=<B,C,D,B> 是序列X=<A,B,C,B,D,A,B>的子序列;
给定两个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X,Y的公共子序列。
例如,若X=<A,B,C,B,D,A,B>,Y=<B,D,C,A,B,A>,
那么:<B,C,A>是X和Y的一个公共子序列,<B,C,B,A>也是X和Y的一个公共子序列;
编程求出给定的两个序列中,最长公共子序列的长度。
输入
共两行,各一个字符串,第一个字符串表示第一个序列,第二个字符串表示第二个序列,两个字符串长度均小于1000。
输出
一个整数,即两个序列的公共子序列的长度。
样例输入
aabaaecd
abcd
样例输出
4
思路分析
a a b a a e c d a 1 1 1 1 1 1 1 1 b 1 1 2 2 2 2 2 2 c 1 1 2 2 2 2 3 3 d 1 1 2 2 2 2 3 4 动态规划。
dp[i][j]存储 字符串a的前i个字符 与 字符串b的前j个字符 的公共子序列的最大长度。
当a[i]=b[j]时,更新dp[i][j]=dp[i-1][j-1]+1。
当a[i]≠b[j]时,更新dp[i][j]=max(dp[i-1][j],dp[i][j-1])。
以本题样例为例,求解两字符串最长公共子序列长度,本质就是构建以上二维表格。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int m,n;
string a,b;
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>a>>b;m=a.size();n=b.size();vector<vector<int>>dp(m+1,vector<int>(n+1,0));for(int i=1;i<=m;i++){for(int j=1;j<=n;j++){if(a[i-1]==b[j-1]){dp[i][j]=dp[i-1][j-1]+1;}else{dp[i][j]=max(dp[i-1][j],dp[i][j-1]);}}}cout<<dp[m][n];return 0;
}