zoukankan      html  css  js  c++  java
  • L3-020 至多删三个字符 (30 分) 线性dp

      

    给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串?

    输入格式:

    输入在一行中给出全部由小写英文字母组成的、长度在区间 [4, 1] 内的字符串。

    输出格式:

    在一行中输出至多删掉其中 3 个字符后不同字符串的个数。

    输入样例:

    ababcc
    

    输出样例:

    25
    

    提示:

    删掉 0 个字符得到 "ababcc"。

    删掉 1 个字符得到 "babcc", "aabcc", "abbcc", "abacc" 和 "ababc"。

    删掉 2 个字符得到 "abcc", "bbcc", "bacc", "babc", "aacc", "aabc", "abbc", "abac" 和 "abab"。

    删掉 3 个字符得到 "abc", "bcc", "acc", "bbc", "bac", "bab", "aac", "aab", "abb" 和 "aba"。

    作者: 曹鹏
    单位: Google
    时间限制: 400 ms
    内存限制: 64 MB

     数据到了106  很明显用dp来做

    dp[i][j]表示  前i个字符 删除j个字符的 种类

    1基础的状态转移

    也就是拆与不拆:

    dp[i][j]=dp[i-1][j]+dp[i-1][j-1];

    2判重 

    有些重复的加了多次 要减回去

    例如一个字符串cd abna xy,你删除abn和删除bna后得到的字符串都是cdaxy。(这个区间长度为3)

    这时候就要去重了,根据上面那个例子可以发现对于一个字符s[i],如果在i之前存在一个x使得s[x]=s[i],那么删除[x,i-1]间的字符 和删除[x+1,i]间的字符其实是重复的,等价的,那么d[i][j]就要减去d[x-1][j-(i-x)],减去删除这段造成的重复串。

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define LL long long
    #define pb push_back
    #define fi first
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    ///////////////////////////////////
    #define inf 0x3f3f3f3f
    #define N 10000000+5
    LL dp[N][4];
    char s[N];
    int pos[N];
    int main()
    {
       RS(s+1);
       int len=strlen(s+1);
       dp[0][0]=1;
       rep(i,1,len)
       {
        dp[i][0]=1;
        int ch=s[i]-'a';
        int d=pos[ch];
        pos[ch]=i;
           rep(j,1,3)
           {
               dp[i][j]+=dp[i-1][j]+dp[i-1][j-1];
               if(d&&j-i+d>=0)
                dp[i][j]-=dp[d-1][j-i+d];
           }
       }
        printf("%lld",dp[len][0]+dp[len][1]+dp[len][2]+dp[len][3] );
        return 0;
    }
  • 相关阅读:
    重构代码
    我的菜单在母版页,如何更改菜单点击后的效果
    ASP.NET网页显示LED字体
    点击一次铵钮产生一个新文本框,分别输入值,然后获取
    linux不同信号之间发送信号测试
    UCOSII移植ARM的笔记
    C语言 return返回值的作用
    C语言 return没有返回值.
    linux c语言链表的简单应用之创建链表
    sizeof与strlen的用法
  • 原文地址:https://www.cnblogs.com/bxd123/p/10610666.html
Copyright © 2011-2022 走看看