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. 先把空字符也考虑进去(好写状态转移方程),最后减个1就好了
2. 一开始是把状态分为2种,dp[i][0]表示到i位置,并且i位置的字符没用;dp[i][1]表示到i位置,并且i位置的字符用了,而且不能与dp[i][0]有重复。
dp[i][0]还比较好算,直接就是
但是dp[i][1]就存在重复情况了,而且不能与dp[i][0]有重复,所以需要记录上一次用S[i]字符结尾的结果,
而记录上一次某个字符的prev,因为dp[i][1]表示跟dp[i][0]不存在重复的情况,也就是跟prev中的key不重复,所以prev更新策略就是:
class Solution:
def distinctSubseqII(self, S):
"""
:type S: str
:rtype: int
"""
mod=10**9+7
dp=[[0,0] for _ in range(len(S))]
dp[0]=[1,1]
prev={S[0]:1}
for i in range(1,len(S)):
dp[i][0]=(dp[i-1][1]+dp[i-1][0])%mod
dp[i][1]=(dp[i-1][1]+dp[i-1][0]-prev.get(S[i],0))%mod
prev[S[i]]=prev.get(S[i],0)+dp[i][1]
return sum(dp[-1])%mod-1
s=Solution()
print(s.distinctSubseqII("abc"))
print(s.distinctSubseqII("aba"))
print(s.distinctSubseqII("aaa"))
其实这个解法写完也没有底(想法比较绕),莽交OJ居然A了。
后来看了下代码,发现其实可以写得简单些,想法也更简单些。可以把2个状态合起来,dp[i]表示到i位置所有可能sub-seq数目,然后其实我们要减去的就是之前使用S[i]字符的结果,比如前一个S[i]出现的位置是j,那前一个使用了S[i]的不就是dp[j-1]吗
class Solution:
def distinctSubseqII(self, S):
"""
:type S: str
:rtype: int
"""
mod=10**9+7
dp=[0 for _ in range(len(S))]
dp[0]=2
prev={S[0]:1}
for i in range(1,len(S)):
dp[i]=2*dp[i-1]-prev.get(S[i],0)
dp[i]%=mod
prev[S[i]]=dp[i-1]
return dp[-1]%mod-1
s=Solution()
print(s.distinctSubseqII("abc"))
print(s.distinctSubseqII("aba"))
print(s.distinctSubseqII("aaa"))