zoukankan      html  css  js  c++  java
  • [leetcode]115. Distinct Subsequences 计算不同子序列个数

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

    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).

    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
    ^^^ ^^^

    题意:

    给定字符串S和T,求字符串S中有多少种不同的subsequences能完全match字符串T

    思路:

    这是一道高频dp题,需要熟练掌握

    注意区分substring(要求连续)和subsequence(不要求连续)

    进一步理解题意,

    S : rabbbit  删掉第一个‘b’ , 可以跟T完全match
    S : rabbbit  删掉第二个‘b’ , 可以跟T完全match
    S : rabbbit  删掉第三个‘b’ , 可以跟T完全match

    return 3 (number of distinct subsequences)

    用dp[i][j]来记录S的子序列跟T匹配的个数

    初始化的时候,除了要处理dp[0][0],还要条件反射的习惯性思考是否需要预处理第一个row : dp[0][j] 和第一个col:dp[i][0]

        T =    0 "r a b b i t"  
            0  1  0 0 0 0 0 0   
     S =   "r  1  1 0 0 0 0 0 
            a  1  1 1 0 0 0 0 
            b  1  1 1 1 0 0 0 
            b  1  1 1 2 1 0 0 
            b  1  1 1 3 ?
            i  1  1
            t  1  1
       

    显然,

    对于是否需要预处理第一个row : dp[0][j], 发现当S为空,T为任意字符都不可能跟S匹配。 对于dp[0][j]不需要多做处理,只保留defalut值为0即可

    对于是否需要预处理第一个col:dp[i][0], 发现当T为空,S的当前字符都可以partition into two subsequences :  " " + 当前字符, 所以dp[i][0] = 1

    对于dp[i][j],

    若 s.charAt(i-1) ! = t.charAt(j-1)  则S当前的字符必须删掉,再看S和T是否匹配: dp[i][j] = dp[i-1][j]

    若 s.charAt(i-1) == t.charAt(j-1)  则S当前的字符要么删掉:dp[i][j] = dp[i-1][j] ; 要么保留:dp[i][j] = dp[i-1][j-1] 

    代码

     1 class Solution {
     2     public int numDistinct(String s, String t) {
     3         int[][] dp = new int[s.length() +1 ][t.length() + 1];
     4         dp[0][0] = 1;
     5         for(int i = 1; i <= s.length() ; i++){
     6             dp[i][0] = 1;
     7         }    
     8         for(int i = 1; i <= s.length() ; i++){
     9             for(int j = 1; j<=t.length(); j++){
    10                 if( s.charAt(i-1) != t.charAt(j-1) ){
    11                     dp[i][j] =  dp[i-1][j];
    12                 }else{
    13                     dp[i][j] =  dp[i-1][j-1] + dp[i-1][j]; 
    14                 }
    15             }
    16         }
    17         return dp[s.length()][t.length()];
    18     }
    19 }

                                       

                

  • 相关阅读:
    IDENT_CURRENT ,@@identity,SCOPE_IDENTITY() 之间对比
    移动无边框窗体
    Winform拖拽改变无边框窗体大小
    配置错误---分析器错误消息: 无法识别的属性“targetFramework”。请注意属性名称区分大小写。
    c# winform中预防窗体重复打开
    C# TreeView 控件的综合使用方法
    c# vs2010 连接access数据库
    解决python pip缓慢
    securecrt密码获取
    linux开启telnet
  • 原文地址:https://www.cnblogs.com/liuliu5151/p/9054194.html
Copyright © 2011-2022 走看看