题意:
图示:
解题思路:
思路:状态定义:dp[i][j]表示:s的前i个字符的子序列中,包含多少个t的前 j 个字符子串转移方程:1. s[i-1]==t[j-1]时 1.1 保留s[i-1],有dp[i-1][j-1]种方法,即:确定s的第i个字符与t的第j个字符对应后,s的前 i-1 个字符有多少种方法变为t的前 j-1 个字符。 1.2 比如:s = 'rabb' t = 'rab' 保留s跟t中的最后一个b,看前面s中rab是否可以组成多少个t中的ra,答案是一个 1.3 不保留s[i-1],有dp[i-1][j]种方法。即:不使用s的第i个字符,s的前 i-1 个字符有多少种方法变为t的前 j 个字符。 1.4 比如:s = 'rabb' t = 'rab' 不保留s中的最后一个b,我们看s中的rab是否可以组成多少个t中的rab,答案也是一个 最终,s[i-1]==t[j-1]时,dp[i][j] = dp[i-1][j-1]+dp[i-1][j]2. s[i-1] != t[j-1]时,有dp[i-1][j]种方法,即:已知s的第 i 个字符不能与t的第 j 个字符对应,s的前 i-1 个字符有多少种方法变为t的前 j 个字符。 比如 s = 'ra' t = 'r' 当s中的a不等于t中的r时,我们看s中除了a前面有几个可以组成t的可能性,即dp[i-1][j]
PHP代码实现:
class Solution { /** * @param String $s * @param String $t * @return Integer */ function numDistinct($s, $t) { $dp = []; for ($i = 0; $i <= strlen($s); $i++) { //$t是空字符串的情况,空字符串也是s的子串 $dp[$i][0] = 1; } for ($i = 1; $i <= strlen($t); $i++) { $dp[0][$i] = 0;//s为空,那就没办法匹配了 } for ($i = 1; $i <= strlen($s); $i++) { for ($j = 1; $j <= strlen($t); $j++) { if ($s[$i-1] == $t[$j-1]) { $dp[$i][$j] = $dp[$i - 1][$j - 1] + $dp[$i - 1][$j]; } else { $dp[$i][$j] = $dp[$i - 1][$j]; } } } return $dp[strlen($s)][strlen($t)]; }}
GO代码实现:
func numDistinct(s string, t string) int { if len(s)==0 || len(s) < len(t) { return 0 } dp := make([][]int, len(s)+1) for i := 0; i <= len(s); i++ { dp[i] = make([]int, len(s) + 1) dp[i][0] = 1 } for i := 1;i <= len(s); i++ { for j := 1;j <= len(t); j++ { if s[i-1] == t[j-1] { dp[i][j] = dp[i-1][j-1] + dp[i-1][j] } else { dp[i][j] = dp[i-1][j] } } } return dp[len(s)][len(t)]}