题目描述
给定一个字符串 S
,计算 S
的不同非空子序列的个数。
因为结果可能很大,所以返回答案模 10^9 + 7
.
示例 1:
输入:"abc" 输出:7 解释:7 个不同的子序列分别是 "a", "b", "c", "ab", "ac", "bc", 以及 "abc"。
示例 2:
输入:"aba" 输出:6 解释:6 个不同的子序列分别是 "a", "b", "ab", "ba", "aa" 以及 "aba"。
示例 3:
输入:"aaa" 输出:3 解释:3 个不同的子序列分别是 "a", "aa" 以及 "aaa"。
提示:
S
只包含小写字母。1 <= S.length <= 2000
解题思路
动态规划,dp[i]定义为以i位置字母结尾的不同子序列个数,当没个字母唯一出现一次时,状态转换方程为dp[i+1] = 2*dp[i],但是根据题目示例,会出现重复的子序列,于是用last[26]记录每个S中的字母最后一次出现的位置,当某一个字母至少出现一次时使用dp[i+1]减去相应的数目就行。
int distinctSubseqII(string S) {
int len=S.length();
int mod = 1e9+7;
int dp[len+1] = {0};
int last[26];
memset(last,-1,sizeof(last));
dp[0]=1;
for(int i=0;i<len;i++){
dp[i+1]=(2*dp[i])%mod;
int idx=S[i]-'a';
if(last[idx]>=0){
dp[i+1]=(dp[i+1]-dp[last[idx]] + mod)%mod;
}
last[idx]=i;
}
dp[len] = (dp[len]-1)%mod;
return dp[len];
}