专栏文章

题解:CF1409F Subsequences of Length Two

CF1409F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minzhngz
此快照首次捕获于
2025/12/02 10:53
3 个月前
此快照最后确认于
2025/12/02 10:53
3 个月前
查看原文

Content

给你两个字符串 sstt,其中 1s200,t=21 \le |s| \le 200, |t| = 2
最多可以修改 kkss 中的字符,问你修改完后 ss 的子序列最多有多少个为 tt

Solution

首先我们注意到“子序列”,而 tt 的长度只有 22,也就是说我们可以记从开头到当前位置出现过多少个 t1t_1,遇到 si=t2s_i = t_2 的情况就直接加上这个个数即可。
有了答案的快速贡献之后,我们考虑如何处理修改。
考虑记 dpi,j,ldp_{i,j,l} 为从开头到第 ii 个位置,共修改了 jj 次,有 llt1t_1(包括修改后的)。那么转移有这几种情况:
  • sit1,t2s_i \neq t_1, t_2,此时初值为 dpi,j,l=dpi1,j,ldp_{i,j,l} = dp_{i-1,j,l}
  • sit1,j1s_i \neq t_1, j \ge 1,此时我们考虑将 sis_i 改为 t1t_1dpi,j,l=max(dpi,j,l,dpi1,j1,l1)dp_{i,j,l} = \max (dp_{i,j,l}, dp_{i-1,j-1,l-1})
  • si=t1s_i = t_1,此时可以直接加个数,dpi,j,l=max(dpi,j,l,dpi1,j,l1)dp_{i,j,l} = \max (dp_{i,j,l}, dp_{i-1,j,l-1})
  • sit2,j1s_i \neq t_2, j \ge 1,此时我们考虑将 sis_i 改为 t2t_2 再加贡献,dpi,j,l=max(dpi,j,l,dpi1,j1,l+l)dp_{i,j,l} = \max (dp_{i,j,l}, dp_{i-1,j-1,l} + l)
  • si=t2s_i = t_2,此时可以直接加贡献,dpi,j,l=max(dpi,j,l,dpi1,j,l+l)dp_{i,j,l} = \max (dp_{i,j,l}, dp_{i-1,j,l} + l)
但我们发现当 si=tis_i = t_i 时,t1t_1 也会有贡献,所以第二,三种真正的转移是需要加上 [t1=t2]×(l1)[t_1 = t_2] \times (l-1) 的,修改后的转移如下。
  • sit1,j1s_i \neq t_1, j \ge 1 时,dpi,j,l=max(dpi,j,l,dpi1,j1,k1+[t1=t2]×(l1))dp_{i,j,l} = \max (dp_{i,j,l}, dp_{i-1,j-1,k-1} + [t_1 = t_2] \times (l-1))
  • si=t1s_i = t_1 时,dpi,j,l=max(dpi,j,l,dpi1,j,k1+[t1=t2]×(l1))dp_{i,j,l} = \max (dp_{i,j,l}, dp_{i-1,j,k-1} + [t_1 = t_2] \times (l-1))
当然也有从后向前记 t2t_2t1t_1 贡献的方法,只不过倒过来转而已。

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 条评论,欢迎与作者交流。

正在加载评论...