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次修改不一定是最优解,有可能不修改就是最优解,因此在初始化时进行调整

#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;
}
View Code
原文地址:https://www.cnblogs.com/yzccccc/p/13694801.html