Problem

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.

思路

  • 为什么需要从暴力搜索想到动归?
    • 因为这类型的搜索类似一个组合问题, 即从m个character中抽出n个与目标匹配, 所以复杂度为O(2^n)
    • 因为存在overlap subproblem, 所以我们需要记录子状态.
    • 这时候我们只需要知道子状态与父状态的关系式
  • 匹配矩阵
    • if s(i) == t(j), 也就是图中s(4) == t(3)
      • 那么dp[4][3] 来源于dp[3][2] 和dp[3][3]
      • 问题: 为什么和dp[4][2]没有关系?
        • 因为dp[4][2] 来源于 dp[3][2], 并且一模一样
    • else s(i) != t(j), 也就是图中 s(5) != t(5)
      • dp[5][5] 来源于 dp[4][5], 与 dp[4][4] , dp[5][4] 没有关系
    • 图中画椭圆的地方就是需要初始化的地方
  • 写出state, function, initialize, answer四部曲
    public int numDistinct(String S, String T) {
        if (S == null || T == null) {
            return 0;
        }
        int ls = S.length();
        int lt = T.length();

        int[][] dp = new int[ls + 1][lt + 1];
        for (int i = 0; i <= ls; i++) {
            dp[i][0] = 1;
        }

        for (int i = 1; i <= ls; i++) {
            for (int j = 1; j <= lt; 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];
                }
            }
        }
        return dp[ls][lt];
    }

滚动数组优化

    public int numDistinct(String S, String T) {
        if (S == null || T == null) {
            return 0;
        }
        int ls = S.length();
        int lt = T.length();

        int[][] dp = new int[2][lt + 1];
        dp[0][0] = 1;

        for (int i = 1; i <= ls; i++) {
            dp[i%2][0] = 1;
            for (int j = 1; j <= lt; j++) {
                if (S.charAt(i - 1) == T.charAt(j - 1)) {
                    dp[i%2][j] = dp[(i - 1)%2][j - 1] + dp[(i - 1)%2][j];
                } else {
                    dp[i%2][j] = dp[(i - 1)%2][j];
                }
            }
        }
        return dp[ls%2][lt];
    }

results matching ""

    No results matching ""