动态规划,求解《940. 不同的子序列 II》

例题

940. 不同的子序列 II

给定一个字符串 s,计算 s 的 不同非空子序列 的个数。因为结果可能很大,所以返回答案需要对 10^9 + 7 取余 。
字符串的 子序列 是经由原字符串删除一些(也可能不删除)字符但不改变剩余字符相对位置的一个新字符串。
例如,"ace" 是 "abcde" 的一个子序列,但 "aec" 不是。
示例 1:
输入:s = "abc"
输出:7
解释:7 个不同的子序列分别是 "a", "b", "c", "ab", "ac", "bc", 以及 "abc"。
示例 2:
输入:s = "aba"
输出:6
解释:6 个不同的子序列分别是 "a", "b", "ab", "ba", "aa" 以及 "aba"。
示例 3:
输入:s = "aaa"
输出:3
解释:3 个不同的子序列分别是 "a", "aa" 以及 "aaa"。
提示:
1 <= s.length <= 2000
s 仅由小写英文字母组成

答案

当前索引位置的子序列个数 = 每个已出现字母最后出现索引位置(避免重复)的子序列个数和

var distinctSubseqII = function(s) {
  const n = s.length, lastIndexs = new Int16Array(26).fill(-1), dp = new Uint32Array(n).fill(1), MOD = 1e9 + 7
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < 26; j++) {
      if (lastIndexs[j] > -1) dp[i] = (dp[i] + dp[lastIndexs[j]]) % MOD
    }
    lastIndexs[s.charCodeAt(i) - 97] = i
  }
  let r = 0
  for (let j = 0; j < 26; j++) {
    if (lastIndexs[j] > -1) r = (r + dp[lastIndexs[j]]) % MOD
  }
  return r
};
function distinctSubseqII(s: string): number {
  const n = s.length, lastIds = new Int16Array(26).fill(-1), dp = new Uint32Array(n).fill(1)
  const MOD = 1e9 + 7
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < 26; j++) {
      if (lastIds[j] > -1) dp[i] = (dp[i] + dp[lastIds[j]]) % MOD
    }
    lastIds[s.charCodeAt(i) - 97] = i
  }
  let r = 0
  for (let j = 0; j < 26; j++) {
    if (lastIds[j] > -1) r = (r + dp[lastIds[j]]) % MOD
  }
  return r
};
define('MOD', 1e9 + 7);
class Solution {
  function distinctSubseqII($s) {
    $n = strlen($s);
    $dp = array_fill(0, $n, 1);
    $lastIs = array_fill(0, 26, -1);
    for ($i = 0; $i < $n; $i++) {
      for ($j = 0; $j < 26; $j++) {
        if ($lastIs[$j] > -1) $dp[$i] = ($dp[$i] + $dp[$lastIs[$j]]) % MOD;
      }
      $lastIs[ord($s[$i]) - 97] = $i;
    }
    $r = 0;
    for ($j = 0; $j < 26; $j++) {
      if ($lastIs[$j] > -1) $r = ($r + $dp[$lastIs[$j]]) % MOD;
    }
    return $r;
  }
}
func distinctSubseqII(s string) int {
   n, MOD := len(s), int(1e9 + 7)
   dp, lastIds := make([]int, n), make([]int, 26)
   for i := 0; i < n; i++ {
     dp[i] = 1
   }
   for j := 0; j < 26; j++ {
     lastIds[j] = -1
   }
   for i, c := range s {
     for j := 0; j < 26; j++ {
       if lastIds[j] > -1 {
         dp[i] = (dp[i] + dp[lastIds[j]]) % MOD
       }
     }
     lastIds[c - 'a'] = i
   }
   r := 0
   for j := 0; j < 26; j++ {
     if lastIds[j] > -1 {
       r = (r + dp[lastIds[j]]) % MOD
     }
   }
   return r
}
class Solution {
  public int distinctSubseqII(String s) {
    int n = s.length(), MOD = (int)1e9 + 7, r = 0;
    int[] dp = new int[n], lastIs = new int[26];
    for (int i = 0; i < n; i++) dp[i] = 1;
    for (int j = 0; j < 26; j++) lastIs[j] = -1;
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < 26; j++) {
        if (lastIs[j] > -1) dp[i] = (dp[i] + dp[lastIs[j]]) % MOD;
      }
      lastIs[s.charAt(i) - 'a'] = i;
    }
    for (int j = 0; j < 26; j++) {
      if (lastIs[j] > -1) r = (r + dp[lastIs[j]]) % MOD;
    }
    return r;
  }
}
public class Solution {
  public int DistinctSubseqII(string s) {
    int n = s.Length, r = 0, MOD = (int)1e9 + 7;
    int[] dp = new int[n], lastIs = new int[26];
    for (int i = 0; i < n; i++) dp[i] = 1;
    for (int j = 0; j < 26; j++) lastIs[j] = -1;
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < 26; j++) {
        if (lastIs[j] > -1) dp[i] = (dp[i] + dp[lastIs[j]]) % MOD;
      }
      lastIs[s[i] - 'a'] = i;
    }
    for (int j = 0; j < 26; j++) {
      if (lastIs[j] > -1) r = (r + dp[lastIs[j]]) % MOD;
    }
    return r;
  }
}
int distinctSubseqII(char * s){
  int n = strlen(s), MOD = 1e9 + 7, r = 0;
  int* dp = malloc(sizeof(int) * n);
  int* lastIs = malloc(sizeof(int) * 26);
  for (int i = 0; i < n; i++) dp[i] = 1;
  memset(lastIs, -1, sizeof(int) * 26); // memset 只能赋值 0 / -1
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < 26; j++) {
      if (lastIs[j] > -1) dp[i] = (dp[i] + dp[lastIs[j]]) % MOD;
    }
    lastIs[s[i] - 'a'] = i; 
  }
  for (int j = 0; j < 26; j++) {
    if (lastIs[j] > -1) r = (r + dp[lastIs[j]]) % MOD;
  }
  return r;
}
class Solution {
public:
  int distinctSubseqII(string s) {
    int n = s.size(), MOD = 1e9 + 7, r = 0;
    vector<int> dp(n, 1), lastIs(26, -1);
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < 26; j++) {
        if (lastIs[j] > -1) dp[i] = (dp[i] + dp[lastIs[j]]) % MOD;
      }
      lastIs[s[i] - 'a'] = i;
    }
    for (int j = 0; j < 26; j++) {
      if (lastIs[j] > -1) r = (r + dp[lastIs[j]]) % MOD;
    }
    return r;
  }
};
class Solution:
  def distinctSubseqII(self, s: str) -> int:
    n, r, MOD = len(s), 0, 1e9 + 7
    dp, lastIs = [1] * n, [-1] * 26
    for i in range(n):
      for j in range(26):
        if lastIs[j] > -1: dp[i] = (dp[i] + dp[lastIs[j]]) % MOD
      lastIs[ord(s[i]) - 97] = i
    for j in range(26):
      if lastIs[j] > -1: r = (r + dp[lastIs[j]]) % MOD
    return int(r)

栈、顺序遍历,为可变数组添加元素,2 解法求解《1441. 用栈操作构建数组》
栈、顺序遍历,为可变数组添加元素,2 解法求解《1441. 用栈操作构建数组》
贪心算法,求解《769. 最多能完成排序的块》
贪心算法,求解《769. 最多能完成排序的块》
动态规划,求解《801. 使序列递增的最小交换次数》
动态规划,求解《801. 使序列递增的最小交换次数》