• UVa 10069 Distinct Subsequences(经典DP)


    题意:

    给定2个字符串a, b,求b在a中出现的次数。要求可以是不连续的,但是b在a中的顺序必须和b以前的一致。

    思路:

    类似于数字分解的题目。dp[i][j]表示:b的前j个字符在a的前i个字符中出现的次数。

    似乎这种表示方法司空见惯,但是一开始我还真没能搞懂如何去递推。事情的真相是:

    如果a[i] == b[j]则 dp[i][j] = dp[i-1][j] + dp[i-1][j-1]

    如果a[i] != b[j]则 dp[i][j] = dp[i-1][j]

    有种似曾相识的感觉,没错,这种递推的策略就和POJ 1221数字分解差不多:给定数n,把其分解成1-m数字相加之和。

    其实本题可以转换成一维的数组,但是初始化有点撇脚。精力有限,于是就没这么做。

    参考了博客http://www.cppblog.com/syhd142/articles/117881.html

    强大的c++封装与重载,慢慢的掌握。

    ps:上次师兄面试说问到类中const和非const的区别。在本题中可以比较好的体现:

    const修饰的函数只能const类型的才能调用。非const只能调用非const函数。但是关于const的理解还有待于加深。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    
    const int MAXN = 10010;
    const int BASE = 1000000000;
    
    struct bignum {
        int len;
        int data[30];
    
        bignum() : len(0) { }
    
        bignum(const bignum &v) : len(v.len) {
            memcpy(data, v.data, len * sizeof(int));
        }
        bignum(int v) : len(0) {
            while (v > 0)
                data[len++] = v % BASE, v /= BASE;
        }
        bignum &operator = (const bignum &v) {
            len = v.len;
            memcpy(data, v.data, len * sizeof(int));
            return *this;
        }
        int &operator [] (int i) {
            return data[i];
        }
        int operator [] (int i) const {
            return data[i];
        }
    };
    
    bignum operator + (const bignum &a, const bignum &b)
    {
        bignum r;
        int i, carry = 0;
        for (i = 0; i < a.len || i < b.len || 0 < carry; ++i)
        {
            if (i < a.len)
                carry += a[i];
            if (i < b.len)
                carry += b[i];
            r[i] = carry % BASE;
            carry /= BASE;
        }
        r.len = i;
        return r;
    }
    
    bignum dp[MAXN][105];
    char src[MAXN], dst[MAXN];
    
    int main()
    {
        int cases;
        scanf("%d%*c", &cases);
        while (cases--)
        {
            gets(src + 1);
            gets(dst + 1);
    
            int ls, ld;
            ls = strlen(src + 1);
            ld = strlen(dst + 1);
    
            int c = 0;
            for (int i = 1; i <= ls; ++i)
                if (src[i] == dst[1])
                    dp[i][1] = bignum(++c);
                else 
                    dp[i][1] = bignum(c);
    
            for (int i = 2; i <= ls; ++i)
            {
                for (int j = 2; j <= ld; ++j)
                {
                    dp[i][j] = dp[i-1][j];
                    if (src[i] == dst[j])
                       dp[i][j] = dp[i][j] + dp[i-1][j-1];
                }
            }
    
            for (int i = dp[ls][ld].len - 1; i >= 0; --i)
                printf("%d", dp[ls][ld][i]);
            printf("\n");
        }
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    AC自动机模板
    hdu 6034 贪心模拟 好坑
    UVA 10870
    hdu 2604 递推 矩阵快速幂
    hdu 3117 Fibonacci Numbers 矩阵快速幂+公式
    hdu 1575 Tr A 矩阵快速幂
    POJ_1151 扫描线+离散化+线段树
    HDU_2227 求不减子序列的个数(树状数组+DP)
    深夜敲模板_5——KMP
    深夜敲模板_4——无向图的割顶和桥
  • 原文地址:https://www.cnblogs.com/kedebug/p/2772906.html
Copyright © 2020-2023  润新知