zoukankan      html  css  js  c++  java
  • 【Distinct Subsequences】cpp

    题目:

    Given a string S and a string T, count the number of distinct subsequences of T in S.

    A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

    Here is an example:
    S = "rabbbit", T = "rabbit"

    Return 3.

    代码:

    class Solution {
    public:
        int numDistinct(string s, string t) {
                const int len_s = s.size();
                const int len_t = t.size();
                if ( len_s<len_t ) return 0;
                if ( len_s==len_t ) return s==t;
                vector<vector<int> > dp(len_t+1,vector<int>(len_s+1,0));
                // initialization
                dp[0][0] = 1;
                for ( int i=1; i<=len_s; ++i ) dp[0][i] = 1;
                // dp process
                for ( int i=1; i<=len_t; ++i )
                {
                    for ( int j=1; j<=len_s; ++j )
                    {
                        if ( t[i-1]!=s[j-1] )
                        {
                            dp[i][j] = dp[i][j-1];
                        }
                        else
                        {
                            dp[i][j] = dp[i][j-1] + dp[i-1][j-1];
                        }
                    }
                }
                return dp[len_t][len_s];
        }
    };

    tips:

    这个题目第一次想到的办法是递归:统计一共要删除多少个字符;每层递归删除一个字符;扫描所有情况。 这种递归的解法大集合肯定会超时。

    憋了一会儿dp的解法,这次又把问题想简单了。

    这种字符串比较的题目,涉及到记忆化搜索的,可以用二维dp来做。

    dp[i][j] 表示T[0:i-1]与S[0:j-1]的匹配次数。

    1. 初始化过程,dp[0][i]代表T为空字符,则S若要匹配上T只有把所有字符都删除了一种情况。

    2. 状态转移方程:dp[i][j]如何求解?

     这里的讨论点其实很直观,即S[j-1]这个元素到底是不是必须删除

      a) 如果T[i-1]!=S[j-1],则S[j-1]必须得删除(因为这是最后一个元素,不删肯定对不上T[i-1]); 因此 dp[i][j] = dp[i][j-1],跟S少用一个字符匹配的情况是一样的。

      b) 如果T[i-1]==S[j-1],则S[j-1]可删可不删;因此dp[i][j] = dp[i][j-1] + dp[i-1][j-1]:

        “dp[i][j-1]”是把S[j-1]删了的情况;“dp[i-1][j-1]”是不删除S[j-1]的情况,即用S[j-1]匹配上T[i-1]

    按照上述的分析过程,可以写出来DP过程。完毕。

    ===========================================

    第二次过这道题,没想出来思路,照着之前的思路写的。

    class Solution {
    public:
        int numDistinct(string s, string t) {
                int dp[s.size()+1][t.size()+1];
                fill_n(&dp[0][0], (s.size()+1)*(t.size()+1), 0);
                dp[0][0] = 1;
                for ( int i=1; i<=s.size(); ++i ) dp[i][0] = 1;
                // dp process
                for ( int i=1; i<=s.size(); ++i )
                {
                    for ( int j=1; j<=t.size(); ++j )
                    {
                        if ( s[i-1]==t[j-1] )
                        {
                            dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
                        }
                        else
                        {
                            dp[i][j] = dp[i-1][j];
                        }
                    }
                }
                return dp[s.size()][t.size()];
        }
    };
  • 相关阅读:
    git 提交解决冲突(转载)
    impala系列: 时间函数
    impala系列: 字符串函数
    Impala系列: Impala常用的功能函数
    impala系列:impala特有的操作符
    impala系列: 同步Hive元数据和收集统计信息
    ETL脚本的版本管理方法和 SourceTree 使用
    几本不错的数据仓库和Hadoop书籍
    Kudu系列-基础
    sql parser
  • 原文地址:https://www.cnblogs.com/xbf9xbf/p/4552886.html
Copyright © 2011-2022 走看看