【Leetcode940】不同的子序列 II

1.题目

给定一个字符串 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 仅由小写英文字母组成

2.分析思路

这个方法是一个acmer和我一起慢慢分析得出,大致过程就是动态规划。

设状态dp[i]: 以位置i结尾的子序列个数.如字符串“abc”

dp[0]=1,就一个a;dp[1]=2,以字符b结尾的子序列的数目:b、ab;dp[2]=4;c,ac,bc,abc;

abc的子序列个数为dp[0]+dp[1]+dp[2]=1+2+4=7;


如字符"aba"

dp[0]=1,a;dp[2]=2,b,ab;dp[3]=3,aa,ba,aba;

aba子序列的个数为dp[0]+dp[1]+dp[2]=1+2+3=6;


从上述分析可以得出,当字符串没有重复字符时,dp[i+1]=dp[i]+dp[i-1]+....+dp[0]+1;

最后的子序列的个数:


但是当字符串中有重复子串的时候:

需要减去重复的值,并且更新i位置的dp[i]及之后的dp[i+1].....

如字符"aba"

dp[0]=1,a;

dp[2]=2,b,ab;

dp[3]=3=(4-1),aa,ba,aba,(a);

aba子序列的个数为dp[0]+dp[1]+dp[2]=1+2+3=6;

这我实现的不太好,使用了暴力方法进行遍历dp,更新dp,时间复杂度较高。

3.代码实现

class Solution {
    public int sum=0;
    public int summ(int a[],int num)
    {
        int results=0;
        for(int i=0;i<num;i++)
        {
            //System.out.println("遍历num:"+a[i]);
            results=(int)((results+a[i])%(Math.pow(10,9)+7));
        }
        return results;
    }
    public int distinctSubseqII(String s) {
        int results=0;
        Map<Character,ArrayList<Integer>>map=new HashMap<Character,ArrayList<Integer>>();//数据结构
        int leng=s.length();
        int nums[] =new int[leng];
        nums[0]=1;
        double M=Math.pow(10,9)+7;
        for(int i=0;i<s.length();i++)//获取是否重复的值
        {
            //ArrayList<Integer> list=new ArrayList<Integer>();
            Character c=s.charAt(i);
            boolean b = map.containsKey(c);
            if(b)
            {
                //System.out.println("存在"+b);
               ArrayList<Integer> value = map.get(c);
               value.add(i);
            }
            else
            {
                ArrayList<Integer> value=new ArrayList<Integer>();
                value.add(i);
                map.put(c,value);
            }
        }
        for(int i=1;i<s.length();i++)
        {
            sum=(int)((sum+nums[i-1])%(M));
            nums[i]=(int)((sum+1)%(M));
        }
        sum=(int)((sum+nums[s.length()-1])%(M));
        results=(int)sum;
        int dif[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        if(map.size() !=s.length() && map.size()!=1)
        {
            for(int x=0;x<s.length();x++)
            {
                int t=s.charAt(x)-'a';
                if(dif[t]!=0)
                {
                    nums[x]=(int)((nums[x]-dif[t])%(M));
                    if(nums[x]<0)
                    {
                         nums[x]+=(int)M;
                    }
                    int index=x;
                    sum=(int)((summ(nums,index+1))%(M));
                    while(index<(s.length()-1))//求新的dp
                    {
                        //Character key=s.charAt(index);
                        nums[index+1]=(int)((sum+1)%(M));
                        sum=(int)((sum+nums[index+1])%(M));
                        index++;
                    }
                }
                dif[t]=(int)((dif[t]+nums[x])%(M));
            }
            results=summ(nums,s.length());
        }
        else if(map.size() == 1)
            results=s.length();
        return results;
    }
}

 

posted @ 2022-10-17 19:47  追·不逝  阅读(32)  评论(0编辑  收藏  举报