• H. Subsequences (hard version) dp


    H. Subsequences (hard version)

    这个题目好难啊,根本就不知道怎么dp,看了题解,理解了好一会才会的。

    首先dp[i][j] 表示前面 i  个字符,形成长度为 j  的不同子字符串的个数。

    dp[i][j]=dp[i-1][j-1]+dp[i][j-1]  这个就是说这个字符选还是不选。

    但是需要注意的是,这个会有重复的字符,如果碰到重复的字符了,这样转移就会出现一点问题,这样会多加了一些情况。

    比如说 xyzabca  dp[7][2] 就是在前面7个字符里面选长度为2的字符的数量,dp[7][2]=dp[6][1]+dp[6][2]

    dp[6][1]转移过来,意味着这个第7个字符一定要选,所以就会有xa yx za这种答案,

    但是这种答案在dp[4][2]=dp[3][1]+dp[3][2]这里转移的时候,dp[3][1]就已经包含了这种答案,所以要删去dp[3][1]

    总的来说就是如果一个字符x前面已经出现过,那么就要删去以字符x结尾的该长度减1的子序列。

    即 dp[i][j]-=dp[pre[i]-1][j-1]

    知道这些了就可以敲代码了。 

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <vector>
    #include <cstdlib>
    #include <iostream>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    ll dp[110][110];
    int pre[110];
    char s[maxn];
    
    int main(){
        ll n,k;
        scanf("%lld%lld",&n,&k);
        scanf("%s",s+1);
        dp[0][0]=1;
        for(int i=1;i<=n;i++){
            dp[i][0]=1;
            for(int j=1;j<=i;j++){
                dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
                if(pre[s[i]-'a']) dp[i][j]-=dp[pre[s[i]-'a']-1][j-1];
                dp[i][j]=min(dp[i][j],k);
            }
            pre[s[i]-'a']=i;
        }
        ll sum=0,ans=0;
        bool flag=0;
        for(int i=n;i>=0;i--){
            if(sum+dp[n][i]>=k){
                flag=1;
                ans+=(n-i)*1ll*(k-sum);
                break;
            }
            sum+=dp[n][i];
            ans+=(n-i)*dp[n][i];
        }
        if(flag) printf("%lld
    ",ans);
        else printf("-1
    ");
        return 0;
    }
    View Code
  • 相关阅读:
    asp.net 正则表达式
    字符串分隔
    用定时器实现逐渐放大层的功能
    js获取剪贴板内容
    使用无线网卡共享上网
    使用事件探查器跟踪sqlserver进程
    document.all.WebBrowser.ExecWB
    (转)JAVA与.NET DES加密解密
    web打印的实现
    关于div的定位
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11620762.html
Copyright © 2020-2023  润新知