算法题LC46:distinct-subsequences

字符串,动态规划:
题目描述
给定一个字符串S和一个字符串T,计算S中的T的不同子序列的个数。
字符串的子序列是由原来的字符串删除一些字符(也可以不删除)在不改变相对位置的情况下的剩余字符(例如,"ACE"is a subsequence of"ABCDE"但是"AEC"不是)
例如:
S =“rabbbit”, T =“rabbit”
返回3

Given a string S and a string T, count the number of distinct subsequences of T in S.
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie,"ACE"is a subsequence of"ABCDE"while"AEC"is not).
Here is an example:
S =“rabbbit”, T =“rabbit”
Return3.
输入描述

输出描述

示例1:
输入

输出
        

下方思路引自:https://www.nowcoder.com/questionTerminal/ed2923e49d3d495f8321aa46ade9f873?f=discussion
来源:牛客网
我们需要一个二维数组dp(i)(j)来记录长度为i的字串在长度为j的母串中出现的次数,这里长度都是从头算起的,而且遍历时,保持子串长度相同,先递增母串长度,母串最长时再增加一点子串长度重头开始计算母串。

首先我们先要初始化矩阵,当子串长度为0时,所有次数都是1,当母串长度为0时,所有次数都是0.当母串子串都是0长度时,次数是1(因为都是空,相等)。接着,如果子串的最后一个字母和母串的最后一个字母不同,说明新加的母串字母没有产生新的可能性,可以沿用该子串在较短母串的出现次数,所以dp(i)(j) = dp(i)(j-1)。如果子串的最后一个字母和母串的最后一个字母相同,说明新加的母串字母带来了新的可能性,我们不仅算上dp(i)(j-1),也要算上新的可能性。那么如何计算新的可能性呢,其实就是在既没有最后这个母串字母也没有最后这个子串字母时,子串出现的次数,我们相当于为所有这些可能性都添加一个新的可能。所以,这时dp(i)(j) = dp(i)(j-1) + dp(i-1)(j-1)。下图是以rabbbit和rabbit为例的矩阵示意图。计算元素值时,当末尾字母一样,实际上是左方数字加左上方数字,当不一样时,就是左方的数字。
在这里插入图片描述

代码:

public class Solution {
     public int numDistinct(String S, String T) {
int length=T.length()+1;
int width=S.length()+1;
int[][]num=new int[length][width];
for(int i=0;i<length;i++)
    num[i][0]=0;
for(int n=0;n<width;n++)
    num[0][n]=1;
for(int j=1;j<length;j++)
    for(int m=1;m<width;m++)
    {
        if(S.charAt(m-1)==T.charAt(j-1))
        {num[j][m]=num[j][m-1]+num[j-1][m-1]; }
        else num[j][m]=num[j][m-1];
    }
 
return num[length-1][width-1];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值