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

    问题描述:

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

    输入格式:

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

    输出格式:

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


    解法:

    d[i][j]表示前i个字符,删掉j个字符的方案数,
    转移方程:d[i][j]=d[i-1][j]+d[i-1][j-1],(对应删和不删)
    但是这样会重复计算,例如
    caba,删除ab和删除ba得到的串是一样的,
    记pre[s[i]]为s[i]上一次出现的位置,
    设x=pre[s[i]]那么d[i][j]-=d[x-1][j-(i-x)],
    为什么这样减?
    因为重复匹配的部分是d[x-1][j-(i-x)],需要减掉一次.
    

    ACcode

    // Author : RioTian
    // Time : 20/11/24
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e6 + 10;
    ll n, dp[N][4], pre[26];
    string s;
    int main() {
        // freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
        cin >> s;
        s = "a" + s, n = s.length() - 1;
        dp[0][0] = 1;
        for (int i = 1; i <= n; ++i) {
            dp[i][0] = 1;
            int x = pre[s[i] - 'a'];
            for (int j = 1; j <= 3 && j <= i; ++j) {
                dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
                if (x && j - (i - x) >= 0)
                    dp[i][j] -= dp[x - 1][j - (i - x)];
            }
            pre[s[i] - 'a'] = i;
        }
        ll ans = 0;
        for (int i = 0; i <= 3; ++i)
            ans += dp[n][i];
        cout << ans << endl;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    面向对象设计原则
    面向对象设计流程
    mysql远程连接命令(转)
    如何使用matplotlib绘制一个函数的图像
    svn:ignore eclipse开发一般忽略文件
    zookeeper client 常用操作
    pip使用
    vi常用快捷键
    python常用函数
    RabbitMQ 学习记录
  • 原文地址:https://www.cnblogs.com/RioTian/p/14032522.html
Copyright © 2011-2022 走看看