1. 程式人生 > >LeetCode115不同的子序列

LeetCode115不同的子序列

問題描述

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

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

示例 1:

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

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

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^

示例 2:

輸入: S = "babgbag", T = "bag"
輸出: 5
解釋:

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

babgbag
^^ ^
babgbag
^^    ^
babgbag
^    ^^
babgbag
  ^  ^^
babgbag
    ^^^

解題思路

本題也是字串匹配問題,與剛剛做過的 第97題 的解題思路很相似。

這類問題,考慮使用一個二維動態dp陣列進行動態規劃求解。

二維動態陣列的使用中,一般也會有幾個步驟:

  1. 初始化陣列
  2. 初始化第一列或者是第一行
  3. 計算DP陣列中的值

先看圖:

行表示子序列T,列表示父序列S,使用T來匹配S中的字元。

當匹配到的字元的位置為 matrix[i][j] 時,則繼續匹配時,不能再選當前列之前的字元了,所以在下一行中,只能從 j+1 列開始匹配。

然後整理以上的規則,計算每個元素的值。

先初始化第一行與第一列,分析可得,第一行中,為 T 的位置的值都可以賦為1,第一列中的非第一行的元素的值,都應該為0。

根據上面分析的計算規律可得,對矩陣中的某個位置 matrix[i][j] 其值為 matrix[i-1][0:j]的和。計算結果如下圖所示:

最終我們所求的結果值為:最後一行的 sum()

程式碼實現

Github Python3 程式碼實現

核心程式碼:

class Solution:
    def numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        col = len(s)
        row = len(t)

        if row > col:
            return 0

        matrix = []

        for i in range(row):
            matrix.append([0] * col)

        # 初始化矩陣
        for i in range(row):
            for j in range(col):
                if t[i] == s[j]:
                    matrix[i][j] = "X"

        # 初始化第一行
        for j in range(col):
            if matrix[0][j] == "X":
                matrix[0][j] = 1

        # 初始化第一列
        for i in range(row):
            if matrix[i][0] == "X":
                matrix[i][0] = 0

        # 計算矩陣中的值
        for i in range(1, row):
            for j in range(1, col):
                if matrix[i][j] == "X":
                    matrix[i][j] = sum(matrix[i - 1][0:j])

        return sum(matrix[row-1])