LeetCode Day57

54 阅读3分钟

392. 判断子序列

给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。 进阶: 如果有大量输入的 S,称作 S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码? 致谢: 特别感谢 @pbrother添加此问题并且创建所有测试用例。

示例 1: 输入:s = "abc", t = "ahbgdc" 输出:true 示例 2: 输入:s = "axc", t = "ahbgdc" 输出:false

提示:

  • 0 <= s.length <= 100
  • 0 <= t.length <= 10^4
  • 两个字符串都只由小写字符组成。

思路

  1. 确定 dp 数组(dp table)以及下标的含义
  • dp[i][j]:表示字符串 s 的前 i 个字符是否是字符串 t 的前 j 个字符的子序列。
  1. 确定递推公式
  • s[i-1] == t[j-1] 时,dp[i][j] = dp[i-1][j-1]
  • s[i-1] != t[j-1] 时,dp[i][j] = dp[i][j-1]
  1. dp 数组如何初始化
  • dp[0][j] = true,空字符串是任何字符串的子序列。
  • dp[i][0] = false,非空字符串不能是空字符串的子序列。
  1. 确定遍历顺序 从前往后遍历。
  2. 举例推导 dp 数组s = "abc"t = "ahbgdc" 为例,最终 dp[3][6] = true

题解

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int m = s.size(), n = t.size();
        vector<vector<bool>> dp(m + 1, vector<bool>(n + 1, false));
        
        // 初始化
        for (int j = 0; j <= n; ++j) {
            dp[0][j] = true;
        }
        
        // 动态规划
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (s[i-1] == t[j-1]) {
                    dp[i][j] = dp[i-1][j-1];
                } else {
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        
        return dp[m][n];
    }
};

115. 不同的子序列

给你两个字符串 s 和 t ,统计并返回在 s 的 子序列 中 t 出现的个数,结果需要对 109 + 7 取模。 示例 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

提示:

  • 1 <= s.length, t.length <= 1000
  • s 和 t 由英文字母组成

思路

  1. 确定 dp 数组(dp table)以及下标的含义
  • dp[i][j]:表示字符串 s 的前 i 个字符中,t 的前 j 个字符出现的次数。
  1. 确定递推公式
  • s[i-1] == t[j-1] 时,dp[i][j] = dp[i-1][j-1] + dp[i-1][j]
  • s[i-1] != t[j-1] 时,dp[i][j] = dp[i-1][j]
  1. dp 数组如何初始化
  • dp[i][0] = 1,因为空字符串是任何字符串的子序列。
  • dp[0][j] = 0,当 j > 0 时,非空字符串不能是空字符串的子序列。
  1. 确定遍历顺序 从前往后遍历。
  2. 举例推导 dp 数组s = "rabbbit"t = "rabbit" 为例,最终 dp[7][6] = 3

题解

class Solution {
public:
    int numDistinct(string s, string t) {
        int m = s.size(), n = t.size();
        vector<vector<long long>> dp(m + 1, vector<long long>(n + 1, 0));
        
        // 初始化
        for (int i = 0; i <= m; ++i) {
            dp[i][0] = 1;
        }
        
        // 动态规划
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                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];
                }
                dp[i][j] %= 1000000007;
            }
        }
        
        return dp[m][n];
    }
};