Distinct Subsequences II
HardUpdated: Aug 2, 2025
Practice on:
Problem
Given a string s, return the number of distinct non-empty subsequences of s. Since the answer may be very large, return it modulo 109 + 7.
A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., "ace" is a subsequence of "abcde" while "aec" is not.
Examples
Example 1
Input: s = "abc"
Output: 7
Explanation: The 7 distinct subsequences are "a", "b", "c", "ab", "ac", "bc", and "abc".
Example 2
Input: s = "aba"
Output: 6
Explanation: The 6 distinct subsequences are "a", "b", "ab", "aa", "ba", and "aba".
Example 3
Input: s = "aaa"
Output: 3
Explanation: The 3 distinct subsequences are "a", "aa" and "aaa".
Constraints
1 <= s.length <= 2000sconsists of lowercase English letters.
Solution
Method 1 – Dynamic Programming with Last Occurrence
Intuition
Every new character can be added to all existing subsequences to form new ones, but we must avoid double-counting subsequences that end with the same character seen before.
Approach
- Let
dp[i]be the number of distinct subsequences for the prefix of lengthi. - For each character, double the count (add the character to all previous subsequences), but subtract the count from the last time this character appeared.
- Use an array to track the last position of each character.
- Return
dp[n] - 1(subtract the empty subsequence).
Code
C++
class Solution {
public:
int distinctSubseqII(string s) {
int n = s.size(), mod = 1e9+7;
vector<int> dp(n+1); dp[0] = 1;
vector<int> last(26, -1);
for (int i = 0; i < n; ++i) {
dp[i+1] = (2LL * dp[i]) % mod;
int c = s[i] - 'a';
if (last[c] != -1) dp[i+1] = (dp[i+1] - dp[last[c]] + mod) % mod;
last[c] = i;
}
return (dp[n] - 1 + mod) % mod;
}
};
Go
func distinctSubseqII(s string) int {
n, mod := len(s), int(1e9+7)
dp := make([]int, n+1)
dp[0] = 1
last := make([]int, 26)
for i := range last { last[i] = -1 }
for i := 0; i < n; i++ {
dp[i+1] = (2 * dp[i]) % mod
c := int(s[i] - 'a')
if last[c] != -1 {
dp[i+1] = (dp[i+1] - dp[last[c]] + mod) % mod
}
last[c] = i
}
return (dp[n] - 1 + mod) % mod
}
Java
class Solution {
public int distinctSubseqII(String s) {
int n = s.length(), mod = 1000000007;
int[] dp = new int[n+1]; dp[0] = 1;
int[] last = new int[26]; Arrays.fill(last, -1);
for (int i = 0; i < n; ++i) {
dp[i+1] = (2 * dp[i]) % mod;
int c = s.charAt(i) - 'a';
if (last[c] != -1) dp[i+1] = (dp[i+1] - dp[last[c]] + mod) % mod;
last[c] = i;
}
return (dp[n] - 1 + mod) % mod;
}
}
Kotlin
class Solution {
fun distinctSubseqII(s: String): Int {
val n = s.length
val mod = 1_000_000_007
val dp = IntArray(n+1); dp[0] = 1
val last = IntArray(26) { -1 }
for (i in 0 until n) {
dp[i+1] = (2L * dp[i] % mod).toInt()
val c = s[i] - 'a'
if (last[c] != -1) dp[i+1] = (dp[i+1] - dp[last[c]] + mod) % mod
last[c] = i
}
return (dp[n] - 1 + mod) % mod
}
}
Python
class Solution:
def distinctSubseqII(self, s: str) -> int:
n, mod = len(s), 10**9+7
dp = [1] + [0]*n
last = [-1]*26
for i, ch in enumerate(s):
dp[i+1] = 2 * dp[i] % mod
c = ord(ch) - ord('a')
if last[c] != -1:
dp[i+1] = (dp[i+1] - dp[last[c]] + mod) % mod
last[c] = i
return (dp[n] - 1) % mod
Rust
impl Solution {
pub fn distinct_subseq_ii(s: String) -> i32 {
let n = s.len();
let modn = 1_000_000_007;
let mut dp = vec![1; n+1];
let mut last = vec![-1; 26];
let s: Vec<u8> = s.into_bytes();
for i in 0..n {
dp[i+1] = (2 * dp[i]) % modn;
let c = (s[i] - b'a') as usize;
if last[c] != -1 {
dp[i+1] = (dp[i+1] - dp[last[c] as usize] + modn) % modn;
}
last[c] = i as i32;
}
((dp[n] - 1 + modn) % modn) as i32
}
}
TypeScript
class Solution {
distinctSubseqII(s: string): number {
const n = s.length, mod = 1e9+7;
const dp = Array(n+1).fill(0); dp[0] = 1;
const last = Array(26).fill(-1);
for (let i = 0; i < n; i++) {
dp[i+1] = (2 * dp[i]) % mod;
const c = s.charCodeAt(i) - 97;
if (last[c] !== -1) dp[i+1] = (dp[i+1] - dp[last[c]] + mod) % mod;
last[c] = i;
}
return (dp[n] - 1 + mod) % mod;
}
}
Complexity
- ⏰ Time complexity:
O(n)wherenis the length of the string. Each character is processed once. - 🧺 Space complexity:
O(n)for the DP array.