CF1409F Subsequences of Length Two
水题大师(
题意:给定两个字符串,给定m次修改机会,求第二个串作为第一个串子序列的最大数量。其中第二个串是长度为2的字符串。
将对标串是两个相同字母的特殊情况先处理;n的范围是200,考虑三维dp
记第二个串为s2,下标从1开始;计算子序列的数量可以通过 当 s1[i]==s2[2]时 sum+=k ,k代表前i个字符中 s2[1]的个数
dp[i][j][k] 代表前i个修改j次 有k个 s1[1] ,状态转移分为 1.不修改;2.s1[i]==s2[1] 3.s1[i]==s2[2]
注意m次修改不一定是最优解,有可能不修改就是最优解,因此在初始化时进行调整
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e5+10; const int mod=998244353; const int inf=0x3f3f3f3f; ll n,cnt=0; ll dp[210][210][210]; int main() { // freopen("../in.in", "r", stdin); // freopen("../out.out","w",stdout); ios::sync_with_stdio(false); ll t, i, j; ll m, x, y,k; cin>>n>>m; char s1[220],s2[5]; cin>>s1+1>>s2+1; if(s2[1]==s2[2]){ cnt=0; for(i=1;i<=n;i++) if(s1[i]==s2[1]) cnt++; cnt+=m; if(cnt>n) cnt=n; cout<<cnt*(cnt-1)/2<<endl; return 0; } memset(dp,-0x3f,sizeof(dp)); for(i=0;i<=m;i++) dp[0][i][0]=0;//这里要将0-m都初始化,存在i<m,使得结果是最优解 for(i=1;i<=n;i++){ for(j=0;j<=m;j++){ for(k=0;k<=i;k++){ dp[i][j][k]=dp[i-1][j][k]; if(s1[i]==s2[1]) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-1]); else if(j) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k-1]); if(s1[i]==s2[2]) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k]+k); else if(j) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k]+k); } } } ll ans=0; for(i=0;i<=n;i++) ans=max(ans,dp[n][m][i]); cout<<ans<<endl; return 0; }