专栏文章
题解:CF1409F Subsequences of Length Two
CF1409F题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minzhngz
- 此快照首次捕获于
- 2025/12/02 10:53 3 个月前
- 此快照最后确认于
- 2025/12/02 10:53 3 个月前
Content
给你两个字符串 和 ,其中 。
最多可以修改 个 中的字符,问你修改完后 的子序列最多有多少个为 。
Solution
首先我们注意到“子序列”,而 的长度只有 ,也就是说我们可以记从开头到当前位置出现过多少个 ,遇到 的情况就直接加上这个个数即可。
有了答案的快速贡献之后,我们考虑如何处理修改。
考虑记 为从开头到第 个位置,共修改了 次,有 个 (包括修改后的)。那么转移有这几种情况:
- ,此时初值为 ;
- ,此时我们考虑将 改为 ,;
- ,此时可以直接加个数,;
- ,此时我们考虑将 改为 再加贡献,;
- ,此时可以直接加贡献,;
但我们发现当 时, 也会有贡献,所以第二,三种真正的转移是需要加上 的,修改后的转移如下。
- 时,;
- 时,。
当然也有从后向前记 加 贡献的方法,只不过倒过来转而已。
Code
CPP#include <bits/stdc++.h>
using namespace std;
const int N = 200 + 5;
int n, k;
string s, t;
long long dp[N][N][N];
int main () {
ios::sync_with_stdio (0);
cin.tie (0); cout.tie (0);
cin >> n >> k;
cin >> s >> t;
s = " " + s, t = " " + t;
// 因为比 max,初始化一个最小值。
memset (dp, -0x7f, sizeof dp);
dp[0][0][0] = 0;
for (int i = 1; i <= n; ++i)
for (int j = 0; j <= k; ++j)
for (int l = 0; l <= n; ++l) {
if (s[i] != t[1] && s[i] != t[2]) dp[i][j][l] = dp[i - 1][j][l]; // 非 t 中元素
// s_i = t_1 时
if (s[i] != t[1] && j >= 1) dp[i][j][l] = max (dp[i][j][l], dp[i - 1][j - 1][l - 1] + (t[1] == t[2]) * (l - 1));
else if (s[i] == t[1]) dp[i][j][l] = max (dp[i][j][l], dp[i - 1][j][l - 1] + (t[1] == t[2]) * (l - 1));
// s_i = t_2 时
if (s[i] != t[2] && j >= 1) dp[i][j][l] = max (dp[i][j][l], dp[i - 1][j - 1][l] + l);
else if (s[i] == t[2]) dp[i][j][l] = max (dp[i][j][l], dp[i - 1][j][l] + l);
}
long long ans = 0;
for (int i = 0; i <= k; ++i) for (int j = 0; j <= n; ++j) ans = max (ans, dp[n][i][j]);
cout << ans;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...