美文网首页算法学习
算法题--求字符串s的子序列为t的可能情况数

算法题--求字符串s的子序列为t的可能情况数

作者: 岁月如歌2020 | 来源:发表于2020-04-30 22:42 被阅读0次
image.png

0. 链接

题目链接

1. 题目

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

It's guaranteed the answer fits on a 32-bit signed integer.

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

2. 思路1: 动态规划

  • 看到两个字符串, 涉及子序列匹配, 目标问题又是求一个数值, 不假思索开始套动态规划
  • 用按照以终为始的思路, 求s的子序列为t, 则s和t的长度就是状态, 目标问题就是s和t都取全部长度, 那么子问题自然就是s左边若干个字符和t左边若干个字符的子序列匹配问题
  • 定义状态: dp[i][j]表示s[0:i]t[0:j]的匹配可能情况数
  • 状态转移方程
对于i = 1~m, j = 1~n
如果s[i - 1] == t[j - 1]:
    则dp[i][j]的可能情况数, 可以按照互斥条件分成两大类:
    (1) dp[i - 1][j - 1], 表示s[0:i - 1]和t[0:j - 1]的可能情况数, 即s中第i - 1个字符之前的部分和t中第j - 1个字符之前的部分的匹配情况;
    (2) dp[i - 1][j], 表示s[0:i-1]和t[0:j]的可能情况数, 意味着s的第i-1个字符之前的部分和t的第j个字符之前的部分的匹配情况
    
    (1)和(2)是两种独立的情况, 它们共同构成了dp[i][j]的可能来历
否则
    说明s[i - 1]的加入, 并未改变s前面部分和t前面部分的匹配情况, 也就是说
    dp[i][j] = dp[i - 1][j]
  • 初始条件
dp[0][0] = dp[1][0] = ... = dp[m][0] = 1
表示s的前面任意个字符, 和t的空字符的匹配可能性都为1, 直观想法就是因为空字符可以和任何字符匹配

dp[0][1] = dp[0][2] = ... = dp[0][n] = 0
表示s中不取任意字符的结果和t前面任意非0个字符的匹配可能性都为0, 直观想法是非空字符串不可能是空字符串的子序列
  • 返回结果 dp[m][n]
  • 时间复杂度 O(m*n)
  • 空间复杂度 O(m*n)

3. 代码

# coding:utf8


class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        m = len(s)
        n = len(t)
        dp = [[0] * (n + 1) for _ in range(m + 1)]
        dp[0][0] = 1
        for i in range(1, m + 1):
            dp[i][0] = 1
        for j in range(1, n + 1):
            dp[0][j] = 0
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                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[m][n]


solution = Solution()
print(solution.numDistinct('rabbbit', 'rabbit'))
print(solution.numDistinct('babgbag', 'bag'))


输出结果

3
5

4. 结果

image.png

相关文章

  • 算法题--求字符串s的子序列为t的可能情况数

    0. 链接 题目链接 1. 题目 Given a string S and a string T, count t...

  • Manacher's Algorithm算法分析Java

    Manacher's Algorithm俗称马拉车算法,对于求字符串中最长回文子串效率极高。 在求最长回文子串的时...

  • Manacher's Algorithm 的理解

    在 leetcode 刷题刷到求字符串的最长回文字串,而马拉车算法(Manacher's Algorithm), ...

  • 最小窗口子串

    已知字符串S与字符串T,求在S中的最小窗口(区间),使得这个区间中包含 了字符串T中的所有字符。例如: S = “...

  • LeetCode-392-判断子序列

    判断子序列 题目描述:给定字符串 s 和 t ,判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除...

  • Day72 判断子序列

    '''Day72 判断子序列 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 你可以认为 s 和 t ...

  • 蓝杯三十

    算法训练 8-2求完数 时间限制:50.0s 内存限制:256.0MB 提交此题 问题描述 如果一个自然数的...

  • 判断子序列

    给定字符串 s 和 t ,判断 s 是否为 t 的子序列。你可以认为 s 和 t 中仅包含英文小写字母。字符串 t...

  • Leetcode 392 判断子序列

    判断子序列 题目 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 你可以认为 s 和 t 中仅包含英文...

  • 前端分享会--从一道算法题目开始的学习

    算法题 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 理解 所谓回文,...

网友评论

    本文标题:算法题--求字符串s的子序列为t的可能情况数

    本文链接:https://www.haomeiwen.com/subject/vhsxghtx.html