返回介绍

solution / 0100-0199 / 0115.Distinct Subsequences / README_EN

发布于 2024-06-17 01:04:04 字数 7775 浏览 0 评论 0 收藏 0

115. Distinct Subsequences

中文文档

Description

Given two strings s and t, return the number of distinct subsequences of s which equals t.

The test cases are generated so that 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.
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.
babgbag
babgbag
babgbag
babgbag
babgbag

 

Constraints:

  • 1 <= s.length, t.length <= 1000
  • s and t consist of English letters.

Solutions

Solution 1: Dynamic Programming

We define $f[i][j]$ as the number of schemes where the first $i$ characters of string $s$ form the first $j$ characters of string $t$. Initially, $f[i][0]=1$ for all $i \in [0,m]$.

When $i > 0$, we consider the calculation of $f[i][j]$:

  • When $s[i-1] \ne t[j-1]$, we cannot select $s[i-1]$, so $f[i][j]=f[i-1][j]$;
  • Otherwise, we can select $s[i-1]$, so $f[i][j]=f[i-1][j-1]$.

Therefore, we have the following state transition equation:

$$ f[i][j]=\left{ \begin{aligned} &f[i-1][j], &s[i-1] \ne t[j-1] \ &f[i-1][j-1]+f[i-1][j], &s[i-1]=t[j-1] \end{aligned} \right. $$

The final answer is $f[m][n]$, where $m$ and $n$ are the lengths of strings $s$ and $t$ respectively.

The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$.

We notice that the calculation of $f[i][j]$ is only related to $f[i-1][..]$. Therefore, we can optimize the first dimension, reducing the space complexity to $O(n)$.

class Solution:
  def numDistinct(self, s: str, t: str) -> int:
    m, n = len(s), len(t)
    f = [[0] * (n + 1) for _ in range(m + 1)]
    for i in range(m + 1):
      f[i][0] = 1
    for i, a in enumerate(s, 1):
      for j, b in enumerate(t, 1):
        f[i][j] = f[i - 1][j]
        if a == b:
          f[i][j] += f[i - 1][j - 1]
    return f[m][n]
class Solution {
  public int numDistinct(String s, String t) {
    int m = s.length(), n = t.length();
    int[][] f = new int[m + 1][n + 1];
    for (int i = 0; i < m + 1; ++i) {
      f[i][0] = 1;
    }
    for (int i = 1; i < m + 1; ++i) {
      for (int j = 1; j < n + 1; ++j) {
        f[i][j] = f[i - 1][j];
        if (s.charAt(i - 1) == t.charAt(j - 1)) {
          f[i][j] += f[i - 1][j - 1];
        }
      }
    }
    return f[m][n];
  }
}
class Solution {
public:
  int numDistinct(string s, string t) {
    int m = s.size(), n = t.size();
    unsigned long long f[m + 1][n + 1];
    memset(f, 0, sizeof(f));
    for (int i = 0; i < m + 1; ++i) {
      f[i][0] = 1;
    }
    for (int i = 1; i < m + 1; ++i) {
      for (int j = 1; j < n + 1; ++j) {
        f[i][j] = f[i - 1][j];
        if (s[i - 1] == t[j - 1]) {
          f[i][j] += f[i - 1][j - 1];
        }
      }
    }
    return f[m][n];
  }
};
func numDistinct(s string, t string) int {
  m, n := len(s), len(t)
  f := make([][]int, m+1)
  for i := range f {
    f[i] = make([]int, n+1)
  }
  for i := 0; i <= m; i++ {
    f[i][0] = 1
  }
  for i := 1; i <= m; i++ {
    for j := 1; j <= n; j++ {
      f[i][j] = f[i-1][j]
      if s[i-1] == t[j-1] {
        f[i][j] += f[i-1][j-1]
      }
    }
  }
  return f[m][n]
}
function numDistinct(s: string, t: string): number {
  const m = s.length;
  const n = t.length;
  const f: number[][] = new Array(m + 1).fill(0).map(() => new Array(n + 1).fill(0));
  for (let i = 0; i <= m; ++i) {
    f[i][0] = 1;
  }
  for (let i = 1; i <= m; ++i) {
    for (let j = 1; j <= n; ++j) {
      f[i][j] = f[i - 1][j];
      if (s[i - 1] === t[j - 1]) {
        f[i][j] += f[i - 1][j - 1];
      }
    }
  }
  return f[m][n];
}
impl Solution {
  #[allow(dead_code)]
  pub fn num_distinct(s: String, t: String) -> i32 {
    let n = s.len();
    let m = t.len();
    let mut dp: Vec<Vec<u64>> = vec![vec![0; m + 1]; n + 1];

    // Initialize the dp vector
    for i in 0..=n {
      dp[i][0] = 1;
    }

    // Begin the actual dp process
    for i in 1..=n {
      for j in 1..=m {
        dp[i][j] = if s.as_bytes()[i - 1] == t.as_bytes()[j - 1] {
          dp[i - 1][j] + dp[i - 1][j - 1]
        } else {
          dp[i - 1][j]
        };
      }
    }

    dp[n][m] as i32
  }
}

Solution 2

class Solution:
  def numDistinct(self, s: str, t: str) -> int:
    n = len(t)
    f = [1] + [0] * n
    for a in s:
      for j in range(n, 0, -1):
        if a == t[j - 1]:
          f[j] += f[j - 1]
    return f[n]
class Solution {
  public int numDistinct(String s, String t) {
    int n = t.length();
    int[] f = new int[n + 1];
    f[0] = 1;
    for (char a : s.toCharArray()) {
      for (int j = n; j > 0; --j) {
        char b = t.charAt(j - 1);
        if (a == b) {
          f[j] += f[j - 1];
        }
      }
    }
    return f[n];
  }
}
class Solution {
public:
  int numDistinct(string s, string t) {
    int n = t.size();
    unsigned long long f[n + 1];
    memset(f, 0, sizeof(f));
    f[0] = 1;
    for (char& a : s) {
      for (int j = n; j; --j) {
        char b = t[j - 1];
        if (a == b) {
          f[j] += f[j - 1];
        }
      }
    }
    return f[n];
  }
};
func numDistinct(s string, t string) int {
  n := len(t)
  f := make([]int, n+1)
  f[0] = 1
  for _, a := range s {
    for j := n; j > 0; j-- {
      if b := t[j-1]; byte(a) == b {
        f[j] += f[j-1]
      }
    }
  }
  return f[n]
}
function numDistinct(s: string, t: string): number {
  const n = t.length;
  const f: number[] = new Array(n + 1).fill(0);
  f[0] = 1;
  for (const a of s) {
    for (let j = n; j; --j) {
      const b = t[j - 1];
      if (a === b) {
        f[j] += f[j - 1];
      }
    }
  }
  return f[n];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文