leetcode:115. 不同的子序列

1.題目描述

給定一個字符串 S 和一個字符串 T,計算在 S 的子序列中 T 出現的個數。

一個字符串的一個子序列是指,通過刪除一些(也可以不刪除)字符且不干擾剩餘字符相對位置所組成的新字符串。(例如,"ACE" 是 "ABCDE" 的一個子序列,而 "AEC" 不是)

示例 1:

輸入: S = "rabbbit", T = "rabbit"
輸出: 3
解釋:

如下圖所示, 有 3 種可以從 S 中得到 "rabbit" 的方案 (上箭頭符號 ^ 表示選取的字母)


示例 2:

如下圖所示, 有 5 種可以從 S 中得到 "bag" 的方案。 
(上箭頭符號 ^ 表示選取的字母)

2. 解題思路

這是一道動態規劃題目,假設 dp[i][j] 表示字符串 T[0,i-1] 在字符串S[0,j-1]出現次數。

第一步找出狀態轉移方程:

求一般情況下 dp[i][j] 的值。

這裏分兩種情況:①字符串T的第 ( i - 1) 個字符等於字符串S的第( j - 1 )個字符。②兩個字符不相等

第二種比較容易推斷,不相等時,出現次數等於 dp[i][j-1] 次數(相當於刪除字符串S的第( j - 1 )字符)

第一種情況下,出現次數等於 dp[i-1][j-1] + dp[i][j-1] 。這裏得考慮兩種情況,當字符串S的第( j - 1 )字符不刪除時,出現次數跟

dp[i-1][j-1] 相同,刪除情況下,出現次數爲 dp[i][j-1],兩種情況相加可得 dp[i-1][j-1] + dp[i][j-1]。

第二步考慮邊界情況:

當字符串T長度爲 0 時, 出現次數dp[0][x]( 0 =<x <= S長度)皆爲 1(即每個子問題都刪除所有字符)

當字符串S長度爲 0 時, 字符串T的所有子串出現次數都爲0.

爲方便理解,以示例2輸入進行填表:

下標   0 1 2 3 4 5 6 7
  對應字符 0 b a b g b a g
0 0 1 1 1 1 1 1 1 1
1 b 0 1 2 2 2 3 3 3
2 a 0 0 1 1 1 1 4 4
3 g 0 0 0 0 1 1 1 5

 

 

 

 

 

3.示例代碼

class Solution {
    public int numDistinct(String s, String t) {
        int[][] dp = new int[t.length()+1][s.length()+1];
        // 邊界賦值
        for(int i = 0;i < s.length()+1;i++){
            dp[0][i] = 1;
        }
        for(int i = 1;i < t.length()+1;i++){
            for(int j = 1;j < s.length()+1;j++){
                if(s.charAt(j-1) == t.charAt(i-1)){
                    dp[i][j] = dp[i-1][j-1] + dp[i][j-1];
                }else{
                    dp[i][j] = dp[i][j-1];
                }
            }
        }        
        return dp[t.length()][s.length()];

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章