不同的子序列——动态规划

题目链接

思路:
将两个字符串从右向左进行遍历;
s[i] 表示s串中从下标 i 开始到末尾的字符串;
t[j]表示t串中从下标 j 开始到末尾的字符串。

例如 “rara” 与 “ra”
首先都是从末尾的a开始遍历,
若此时 i = 0 ,j = 0,代表“rara“与”ra“匹配的情况,
且 ‘r’ = ’r’ ,匹配,那么此时有两种情况:

  1. 将“rara”中最前面的 ‘r’ 考虑在内,那么与“ra“中最前面的‘r’ 相抵消,只需要考虑”ara“中有多少个”a“即可,则 子序列个数= dp[ i + 1 ][ j + 1]
  2. 不将 ”rara“ 中最前面的‘r’考虑在内,那么则是”rar” 中“ra"的个数, 则子序列个数 = dp[ i + 1][ j ]

将此两种情况相加,则得到了匹配时子序列个数

若不匹配,那么直接等于上述的第二种情况即可。

状态方程:
当s[i] = t[j]时,dp[i][j] = dp[i+1][j+1] + dp[i+1][j]
当s[i] = t[j]时,dp[i][j] = dp[i+1][j]

注意:
当 j = 字符串长度时,此时 t[ j ] 代表空串,该空串为任意字符串的子序列。

代码:

public int numDistinct(String s, String t) {
    
    
        int[][] dp = new int[s.length() + 1][t.length() + 1];
        for (int i = 0; i <= s.length(); i++) {
    
    
            dp[i][t.length()] = 1;
        }

        for (int i = s.length() - 1; i >= 0; i--) {
    
    
            char c = s.charAt(i);
            for (int j = t.length() - 1; j >= 0; j--) {
    
    
                if (c == t.charAt(j)) {
    
    
                    dp[i][j] = dp[i + 1][j + 1] + dp[i + 1][j];
                } else {
    
    
                    dp[i][j] = dp[i + 1][j];
                }
            }
        }

        return dp[0][0];
    }

猜你喜欢

转载自blog.csdn.net/qq_43665244/article/details/114925746