115. 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 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"

Return 3.

链接: http://leetcode.com/problems/distinct-subsequences/

题解:

又一道读题意都很难的题目...又去discussion搬救兵了。看了以后才明白是给定pattern T, 问能在S的subsequence里有多少种包含T。很自然就又想到了dp的解法(当然是看了discussion后...)。 可以这样理解,有一个m x n的矩阵,一个机器人要从左上走到右下,只能向右或者向下走。当s.charAt(j - 1) == t.charAt(i - 1)时可以向下走, 每次向下走时count增加,向右走count不增加,,问到达右下角有多少种方法。  要注意初始化时,当 pattern = "" ,为空字符串时,第一行要初始为1。大家的理解是因为空字符串是任意字符串的subsequence。

Time Complexity - O(mn), Space Complexity - O(mn)。

public class Solution {
    public int numDistinct(String s, String t) {
        if(s == null || t == null)
            return 0;
        int[][] dp = new int[t.length() + 1][s.length() + 1];
        
        for(int j = 0; j < dp[0].length; j++)
            dp[0][j] = 1;
        
        for(int i = 1; i < dp.length; i++) {
            for(int j = 1; j < dp[0].length; j++) {
                if(s.charAt(j - 1) == t.charAt(i - 1))
                    dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
                else
                    dp[i][j] = dp[i][j - 1];
            }
        }
        
        return dp[t.length()][s.length()];
    }
}

这种只依赖上一行的dp一般都可以用滚动数组来优化space complexity, 下面是自己写的比较丑的。用到了Arrays.fill以及 clone()。 有关clone(),doc上并没有说是deep copy还是shallow copy。 在这里应该用deepcopy,不过试了一下clone()居然能work。 有时间的话还是要好好研究。

Time Complexity - O(mn), Space Complexity - O(n)。

public class Solution {
    public int numDistinct(String s, String t) {
        if(s == null || t == null)
            return 0;
        
        int[] last = new int[s.length() + 1];
        int[] res = new int[s.length() + 1];
        for(int j = 0; j < last.length; j++)
            last[j] = 1;
            
        for(int i = 1; i < t.length() + 1; i++) {
            for(int j = 1; j < res.length; j++) {
                if(t.charAt(i - 1) == s.charAt(j - 1)) 
                    res[j] = res[j - 1] + last[j - 1];        
                else 
                    res[j] = res[j - 1];
            }
            last = res.clone();
            Arrays.fill(res, 0);
        }
        
        return last[s.length()];
    }
}

Reference:

https://leetcode.com/discuss/599/task-clarification

http://www.cnblogs.com/springfor/p/3896152.html

https://leetcode.com/discuss/19735/a-dp-solution-with-clarification-and-explanation

https://leetcode.com/discuss/2143/any-better-solution-that-takes-less-than-space-while-in-time

https://leetcode.com/discuss/7945/my-o-n-m-solution-for-your-reference

https://leetcode.com/discuss/26680/easy-to-understand-dp-in-java

原文地址:https://www.cnblogs.com/yrbbest/p/4437336.html