zoukankan      html  css  js  c++  java
  • 动态规划——Distinct Subsequences

    题目大意:给定字符串S和T,现在从S中任选字符组成T,要求输出方案个数。
    Example 1:
    Input: S = "rabbbit", T = "rabbit"
    Output: 3
    Explanation:
    As shown below, there are 3 ways you can generate "rabbit" from S.
    (The caret symbol ^ means the chosen letters)
    rabbbit
    ^^^^ ^^
    rabbbit
    ^^ ^^^^
    rabbbit
    ^^^ ^^^
    Example 2:
    Input: S = "babgbag", T = "bag"
    Output: 5
    Explanation:
    As shown below, there are 5 ways you can generate "bag" from S.
    (The caret symbol ^ means the chosen letters)
    babgbag
    ^^ ^
    babgbag
    ^^    ^
    babgbag
    ^    ^^
    babgbag
      ^  ^^
    babgbag
        ^^^
    这个题的状态就是原问题的子问题:从S[0..i]中选取字符组成T[0..j]的方案数,有时候越做越有感觉:既然是动态规划问题,求解过程中的状态肯定是原问题的子问题(或者说大多数情况下是这样的)。主要问题在于这个状态转移方程,我拿其中一个状态出来说,在数组下标都不越界的情况下,比如说我现在求dp[i][j],方案数包括上一个位置的匹配情况dp[i-1][j-1]乘以(S[i] == T[j])这个布尔的判断值和当次匹配的前一个情况dp[i-1][j],举个例子来说,T[0..1]为“ba”,则dp[i][0]的方案数一定包括S[0..i-1]匹配T[0]=b时的方案数dp[i-1][0]乘以(S[i] == T[0])这个布尔的判断值和S[0..i-1]匹配T[0..1]="ba"时的方案数dp[i-1][1],加后面那项的原因是dp[i][j]肯定是要包括所有匹配了T[j]的方案数量,这个递推关系是2包括1,3包括2,4包括3...这样的包含关系,所以dp[i][j]只需要再加上一个dp[i-1][j]即可。而前面那个乘以布尔值的原因是如果之前匹配到T[j-1]的话前面那个乘积值dp[i-1][j-1]*(S[i] == T[j])可以不加相当于加0,只为了少个if判断,但是后面的dp[i-1][j]还是要加上的。
     
    当然要注意边界条件,我在leetCode上跑程序的时候出现了输入串长度为0的情况导致了数组越界问题。
     
     1 public int numDistinct(String s, String t) {
     2         int slen = s.length();
     3         int tlen = t.length();
     4         if(slen==0||tlen==0)return 0;
     5         if(s.equals(t))return 1;
     6         int[][]dp = new int [slen][tlen];
     7         for(int i = 0;i<slen;i++)
     8             for(int j = 0;j<tlen;j++)
     9                 dp[i][j] = 0;
    10         int temp = 0;
    11         char t0 = t.charAt(0);
    12         for(int i = 0;i<slen;i++) {
    13             if(s.charAt(i)==t0) {
    14                 temp++;
    15                 dp[i][0] = temp;
    16             }else{
    17                 if(i>0)dp[i][0] = dp[i-1][0];
    18                 else dp[i][0] = 0;
    19             } 
    20         }
    21         
    22         for(int i = 1;i<tlen;i++) {
    23             for(int j = i;j<slen;j++) {
    24                 temp = (s.charAt(j)==t.charAt(i))?1:0;
    25                 dp[j][i] = dp[j-1][i]+dp[j-1][i-1]*temp;
    26             }
    27         }
    28         return dp[slen-1][tlen-1];
    29     }
     
  • 相关阅读:
    jQuery中的事件与动画
    jQuery选择器
    Flask学习【第3篇】:蓝图、基于DBUtils实现数据库连接池、上下文管理等
    Flask学习【第2篇】:Flask基础
    Flask学习【第1篇】:Flask介绍
    Python学习总目录
    Linux--安装Python3&虚拟环境
    Linux基础之vim
    Linux基础值Shell
    Linux文件系统结构
  • 原文地址:https://www.cnblogs.com/messi2017/p/9943438.html
Copyright © 2011-2022 走看看