AcWing 897. 线性DP——最长公共子序列

原题链接:

897. 最长公共子序列 - AcWing题库

题解:

第一种理解:

还是按照闫氏DP法来做,状态表示则需要经验积累。

首先定义集合,该集合包含所有A[1~i]与B[1~j]的公共子序列。

接着定义属性,由于我们要获得最长公共子序列,属性便为Max。

f[i][j]表示所有A[1~i]与B[1~j]的公共子序列中的最长公共子序列的长度。

然后就是分析状态计算,根据不重不漏的指导思想,我们将f[i][j]分为4种情况,分别是①既不包含a[i]也不包含b[j];②不包含a[i]但包含b[j];③包含a[i]但不包含b[j];④既包含a[i]也包含b[j]。注意这里的包含指的是一定包含的意思。

对于①而言:其实质就是f[i-1][j-1];

对于②而言:其实质就是f[i-1][j]么?并不完全是,我们之前提到过,这里的包含代表的是一定不包含a[i]但包含b[j]。但是f[i-1][j]的含义是所有A[1~i-1]与B[1~j]的公共子序列中的最长公共子序列的长度,也即一定不包含a[i]但可以包含b[j]也可以不包含b[j-1]。也即f[i-1][j]代表的是②和①的情况。

对于③而言:其实质就是f[i][j-1]么?并不完全是,我们之前提到过,这里的包含代表的是一定包含a[i]但不包含b[j]。但是f[i][j-1]的含义是所有A[1~i]与B[1~j-1]的公共子序列中的最长公共子序列的长度,也即可以包含a[i]也可以不包含a[i]但一定不包含b[j]。也即f[i][j-1]代表的是①和③的情况。

对于④而言:两者相同时一定包含的话就等于f[i-1][j-1]+1。

综上,由于f[i-1][j]代表的是②和①的情况,f[i][j-1]代表的是①和③的情况。所以我们首先可以取这两者之间的最大值,然后再判断情况④即可。

第二种理解:

这题的状态分成两半考虑比较方便,按两个序列末尾的字符是不是相等来区分。

如果两个字符相等,就可以直接转移到f[i-1][j-1],不相等的话,两个字符一定有一个可以抛弃,可以对f[i-1][j],f[i][j-1]两种状态取max来转移。 

代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
int n, m, f[N][N];
char a[N], b[N];

int main() {
	cin >> n >> m >> a + 1 >> b + 1;
	for (int i = 1;i <= n;i++) {
		for (int j = 1;j <= m;j++) {
			if (a[i] == b[j]) f[i][j] = f[i - 1][j - 1] + 1;
			else f[i][j] = max(f[i - 1][j], f[i][j - 1]);
		}
	}
	cout << f[n][m];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值