# 940. Distinct Subsequences II

**<font color=red>难度: Hard</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/distinct-subsequences-ii/

> 内容描述

```
Given a string S, count the number of distinct, non-empty subsequences of S .

Since the result may be large, return the answer modulo 10^9 + 7.

 

Example 1:

Input: "abc"
Output: 7
Explanation: The 7 distinct subsequences are "a", "b", "c", "ab", "ac", "bc", and "abc".
Example 2:

Input: "aba"
Output: 6
Explanation: The 6 distinct subsequences are "a", "b", "ab", "ba", "aa" and "aba".
Example 3:

Input: "aaa"
Output: 3
Explanation: The 3 distinct subsequences are "a", "aa" and "aaa".
 

 

Note:

S contains only lowercase letters.
1 <= S.length <= 2000
```

## 解题方案

> 思路 1
******- 时间复杂度: O(N)******- 空间复杂度: O(N)******


DP

dp[i]代表以S[i-1]为结尾的distinct subsequence的个数

dp[0] = 1，因为一个字符都没有只能是空字符串

如果当前字符s[i-1]之前没有出现过，那么自然我们的d[i] = 2 * dp[i-1]

我们可以用字典存一下之前出现过的字符

beats 100%

```python
class Solution:
    def distinctSubseqII(self, S):
        """
        :type S: str
        :rtype: int
        """
        lookup = {}
        dp = [0] * (len(S)+1)
        dp[0] = 1
        for i in range(1, len(S)+1):
            dp[i] = 2 * dp[i-1]
            if S[i-1] in lookup:
                dp[i] = dp[i] - dp[lookup[S[i-1]]]
            lookup[S[i-1]] = i-1
        return (dp[-1]-1) % (10**9 + 7)
```

> 思路 2
******- 时间复杂度: O(N)******- 空间复杂度: O(1)******



endWith某个字符的思路，见[lee215](https://www.jianshu.com/p/02501f516437)

```
假设当前有N个不同的seq，每个seq加上一个新的字母，又是新的N个不同sequence了。
但新的seq中，有一部分原来就有。
比如新的字母是'a'，那么原来以'a'结尾的seq，每一个都会存在新的这N个seq中。

到这里，解题思路就比较清楚了。
我们需要用一个数组int endsWith[26]，
endsWith[i]来表示以第i个字母结束的sequence数量。

最后修饰一下代码细节。

数组全部初始化为0。
正好按照题目要求，空string不计作subseq。
每次更新的时候，end[i] = sum(end) + 1。
加1的原因是，比如我们遇到新字母'a'，新的N个seq里不包含“a”本身这种情况，需要额外加上。
```

```python
class Solution:
    def distinctSubseqII(self, S):
        """
        :type S: str
        :rtype: int
        """
        end = [0] * 26
        for c in S:
            end[ord(c) - ord('a')] = sum(end) + 1
        return sum(end) % (10**9 + 7)
```

还可以用一个变量保存当前数组和，避免重复计算。

```python
class Solution:
    def distinctSubseqII(self, S):
        """
        :type S: str
        :rtype: int
        """
        res, end = 0, {}
        for c in S:
            res, end[c] = res * 2 + 1 - end.get(c, 0), res + 1
        return res % (10**9 + 7)
```
























