[LintCode] Distinct Subsequence

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).

Example

Given S = "rabbbit", T = "rabbit", return 3.

Challenge

Do it in O(n2) time and O(n) memory.

O(n2) memory is also acceptable if you do not know how to optimize memory.

Solution 1. Recursion

For s[0 ~ n - 1] and t[0 ~ m - 1], there are 2 cases.

case 1. s.charAt(n - 1) != t.charAt(m - 1)

     This means s.charAt(n - 1) can‘t be used in subsequence of t, so f(s[0 ~ n - 1], t[0 ~ m - 1]) = f(s[0 ~ n - 2], t[0 ~ m - 1]).

case 2. s.charAt(n - 1) == t.charAt(m - 1)

      This means s.charAt(n - 1) can be either used or not used in subsequence of t.

    If it is used, there are f(s[0 ~ n - 2], t[0 ~ m - 2]) distinct subsequences of t in s.

    If it is not used, there are f(s[0 ~ n - 2], t[0 ~ m - 1]) distinct subsequences of t in s.

    so f(s[0 ~ n - 1], t[0 ~ m - 1]) = f(s[0 ~ n - 2], t[0 ~ m - 2]) + f(s[0 ~ n - 2], t[0 ~ m - 1]).

Base case 1.  if t is an empty string, then there is 1 distinct subseqnce of empty string in s.

Base case 2.  if t is longer than s, there is no subsequences of t in s.

It‘s clear by drawing recursive tree, that this solution has overlapping problems.

 1 public class DistinctSubsequence {
 2     public int getNumOfDistinctSubsequenceRecursion(String s, String t) {
 3         if(s == null || t == null) {
 4             return 0;
 5         }
 6         return recursiveHelper(s, s.length() - 1, t, t.length() - 1);
 7     }
 8     private int recursiveHelper(String s, int endIdx1, String t, int endIdx2) {
 9         if(endIdx2 < 0) {
10             return 1;
11         }
12         if(endIdx1 < endIdx2) {
13             return 0;
14         }
15         if(s.charAt(endIdx1) != t.charAt(endIdx2)) {
16             return recursiveHelper(s, endIdx1 - 1, t, endIdx2);
17         }
18         return recursiveHelper(s, endIdx1 - 1, t, endIdx2 - 1) + recursiveHelper(s, endIdx1 - 1, t, endIdx2);
19     }
20     public static void main(String[] args) {
21         String s1 = "rabbbit", t1 = "rabbit";
22         String s2 = "aabbccdd", t2 = "abcd";
23         String s3 = "rabbbitt", t3 = "rabbit";
24         String s4 = "", t4 = "";
25         String s5 = "lin", t5 = "lin";
26         String s6 = "lin", t6 = "ling";
27         DistinctSubsequence test = new DistinctSubsequence();
28         System.out.println(test.getNumOfDistinctSubsequenceRecursion(s1, t1));
29         System.out.println(test.getNumOfDistinctSubsequenceRecursion(s2, t2));
30         System.out.println(test.getNumOfDistinctSubsequenceRecursion(s3, t3));
31         System.out.println(test.getNumOfDistinctSubsequenceRecursion(s4, t4));
32         System.out.println(test.getNumOfDistinctSubsequenceRecursion(s5, t5));
33         System.out.println(test.getNumOfDistinctSubsequenceRecursion(s6, t6));
34     }
35 }

Solution 2. Dynamic Programming

State: dp[i][j]: the number of distinct subsequence of T[0... j - 1] in S[0... i - 1]

Function:

If S.charAt(i - 1) can be used to match the last character of T[0...j - 1],  we can either choose to use it or not use it.

If S.charAt(i - 1) can‘t be used to match the last character of T[0...j - 1], we can only choose not to use it.

The above gives us the following state function.

dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j], if S.charAt(i - 1) == T.charAt(j - 1);

dp[i][j] = dp[i - 1][j], if S.charAt(i - 1) != T.charAt(j - 1);

Initialization: dp[0][j] = 0, for j from 1 to T.length(); S is empty string and T is not empty string, no subsequence of T in S;

      dp[i][0] = 1, for i from 0 to S.length(); T is empty string, there is always 1 subsequence of T in S, regardless if S is empty or not.

Answer: dp[S.length()][T.length()]

 1 public class Solution {
 2     public int numDistinct(String S, String T) {
 3         if(S == null || T == null){
 4             return 0;
 5         }
 6         int n = S.length();
 7         int m = T.length();
 8         int[][] dp = new int[n + 1][m + 1];
 9         for(int j = 0; j <= m; j++){
10             dp[0][j] = 0;
11         }
12         for(int i = 0; i <= n; i++){
13             dp[i][0] = 1;
14         }
15         for(int j = 1; j <= m; j++){
16             for(int i = j; i <= n; i++){
17                 if(S.charAt(i - 1) == T.charAt(j - 1)){
18                     dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
19                 }
20                 else{
21                     dp[i][j] = dp[i - 1][j];
22                 }
23             }
24         }
25         return dp[n][m];
26     }
27 }

Related Problems

Interleaving String

时间: 2024-12-07 01:28:25

[LintCode] Distinct Subsequence的相关文章

LeetCode OJ - Distinct Subsequence

这道题采用动态规划,可是我一开始没有想到.后来参考了discuss中前辈的代码和思路,才想通的. 方法二是因为每一步只和上一步的内容相关,所以可以只用O(n)的空间复杂度. 下面是AC代码: 1 /** 2 * Solution DP 3 * we keep a m*n matrix and scanning through string T, 4 * p[i][j] means the number of distinct subsequence of S(0...j) equal to T(

Problem Distinct Subsequence

Problem Desciption : 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 dis

115. distinct subsequence leetcode python

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

CSU 1354 Distinct Subsequences 求不相同子序列的和 dp

题目链接:点击打开链接 Description Give a positive number, count the sum of the distinct subsequence of it, moreover, any subsequence should not contain leading zeroes except it is zero. For example, if the number is 1022, the answer is 1 + 0 + 2 + 10 + 12 + 22

[LeetCode] 940. Distinct Subsequences II

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

[Coding Made Simple] String Interleaving

Given three strings, return true if third string is interleaving of first and second string. By running some examples, it seems that as long as s1.length() + s2.length() == s3.length() and both s1 and s2 are common subsequences of s3, s3 is interleav

LintCode刷题笔记-- Distinct Subsequences

题目描述: 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 rel

Lintcode:Longest Common Subsequence 解题报告

Longest Common Subsequence Given two strings, find the longest comment subsequence (LCS). Your code should return the length of LCS. 样例For "ABCD" and "EDCA", the LCS is "A" (or D or C), return 1 For "ABCD" and "

【leetcode】1081. Smallest Subsequence of Distinct Characters

题目如下: Return the lexicographically smallest subsequence of text that contains all the distinct characters of text exactly once. Example 1: Input: "cdadabcc" Output: "adbc" Example 2: Input: "abcd" Output: "abcd" Exa