给定两个序列,求两个序列的最长公共子序列的长度(暂时先列出来长度好了……)
如此经典的DP,我竟然现在才弄明白,真心弱爆了,好吧,废话不说了,开始吧。
对于两个序列,dp[i][j]表示当第一个序列取前i个元素,第二个序列取前j个元素的时候,最长公共子序列的长度,那么对于此状态,有如下几种推导方式,假设第一个序列是X(x 1 ,x 2 ...x i ),第二个序列是Y(y 1 ,y 2 ...y j ),如果x i =y j ,则dp[i][j]=dp[i-1][j-1]+1,否则,就等于dp[i-1][j]或者dp[i][j-1]。理由如下,假设X和Y的最长公共子序列为Z(z 1 ,z 2 ,...z k ),如果x i =y j ,必然有x i =y j =z k ,如果x i ≠y j ,而且x i ≠z k ,则Z必然是X i-1 和Y的一个最长公共子序列,因为x i 存在与否根本不影响最终的结果,而z k 必然存在于X的前i-1个元素中,否则不成立,同理可运用于Y序列,所以可以得到推导关系。
刚刚把代码YY出来,不知道对不对,希望某一个大牛出来指正一下……
如此经典的DP,我竟然现在才弄明白,真心弱爆了,好吧,废话不说了,开始吧。
对于两个序列,dp[i][j]表示当第一个序列取前i个元素,第二个序列取前j个元素的时候,最长公共子序列的长度,那么对于此状态,有如下几种推导方式,假设第一个序列是X(x 1 ,x 2 ...x i ),第二个序列是Y(y 1 ,y 2 ...y j ),如果x i =y j ,则dp[i][j]=dp[i-1][j-1]+1,否则,就等于dp[i-1][j]或者dp[i][j-1]。理由如下,假设X和Y的最长公共子序列为Z(z 1 ,z 2 ,...z k ),如果x i =y j ,必然有x i =y j =z k ,如果x i ≠y j ,而且x i ≠z k ,则Z必然是X i-1 和Y的一个最长公共子序列,因为x i 存在与否根本不影响最终的结果,而z k 必然存在于X的前i-1个元素中,否则不成立,同理可运用于Y序列,所以可以得到推导关系。
刚刚把代码YY出来,不知道对不对,希望某一个大牛出来指正一下……
特别鸣谢:磊哥ZLGG
#include <cstdio>
#include <cstring>
#include <algorithm>
char x[1111], y[1111];
int dp[1111][1111];
int main(){
scanf("%s", x);
scanf("%s", y);
int lx = strlen(x), ly = strlen(y);
for (int i = 1; i <= lx; i++)
for (int j = 1; j <= ly; j++)
if (x[i] == y[j]) dp[i][j] = std::max(dp[i - 1][j - 1] + 1, std::max(dp[i - 1][j], dp[i][j - 1]));
else dp[i][j] = std::max(dp[i - 1][j], dp[i][j - 1]);
printf("%d\n", dp[lx][ly]);
return 0;
}