LeetCode—115. Distinct Subsequences
题目
https://leetcode.com/problems/distinct-subsequences/description/
子序列问题。给出两个字符串s和t,找出s中有多少子序列等于t。
思路及解法
首先区别子串和子序列。LeetCode—53. Maximum Subarray这道题是子串的问题,我们曾经提到过。子串是在原字符串中每个字符必须是相连的,而子序列则要求更宽泛一些,只要原顺序不变就行了,不需要每个字符是相邻的。
这也是动态规划的问题。因为是两个字符串,所以应该可以能想到是一个二维的dp数组。我们用dp[i][j]表示,s的前i个字符形成的子串,可以表示为t的前j个字符形成的子串的方式数。
考虑递归关系,新来一个字符s[i],如果s[i]!=t[j],那么不能形成新的子串表示方法,所以dp[i][j]=dp[i-1][j];
如果s[i]==t[j],这种情况的表示方式由两部分组成,第一部分dp[i-1][j],s[i]不加入时的表示方式;第二部分,dp[i][j]=dp[i-1][j-1],s[i]加入时的表示方式,我们这样想,既然s[i]和t[j]相等,那么将两者同时拿出去,仍然是一种属于s[i]的子表示方式,并且和上一种方式互斥,所以两者相加就是解果,dp[i][j]=dp[i-1][j]+dp[i-1][j-1]
代码
class Solution {
public int numDistinct(String s, String t) {
int s_len = s.length(), t_len = t.length();
int[][] dp = new int[s_len+1][t_len+1];
dp[0][0] = 1;
for(int i=1; i<=s_len; i++){
dp[i][0] = 1;
}
for(int j=1; j<=t_len; j++){
dp[0][j] = 0;
}
for(int i=1; i<=s_len; i++){
for(int j=1; j<=t_len; j++){
// if(s.charAt(i-1) == t.charAt(j-1)){
// dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
// }else{
// dp[i][j] = dp[i-1][j];
// }
dp[i][j] = dp[i-1][j];
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
}
}
}
return dp[s_len][t_len];
}
}