LeetCode 115. 不同的子序列
基本思想:
本来想用DFS加剪枝,发现不太好写,此次题目没想到还是采用dp思想;
DP方程的问题:
主要难在方程的构建,主旨思想是通过区间判别;
其中dp为二维数组,其中dp[i][j]为s[0:i]和t[0:j]中元素相等个数;
对于0~i个元素,如果s[i]=t[j],可以产生两种0-i-1子序列递归判定思想:
1.如果接受s[i]=t[j],则直接加上dp[i-1][j-1],即判断之前的子序列;
2.如果不接受s[i]=t[j],则判断s[0:i-1]和t[0:j]相同个数(因为t是固定的判定序列,无多于元素);
所以整体的dp状态转移方程为:
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
同理,如果s[i]!=t[j],dp转移方程和第二种情况相同,为:
dp[i][j] = dp[i - 1][j];
DP边界问题:
dp边界分为两种情况:
1.当t的j=0时,只有s清除为0这一种情况,此时s,t完美匹配一次,所以dp[i][0]=1;
2.当s的i=0时,无论什么时候都无法匹配,所以dp[0][j]=0;
整体代码:
int numDistinct(string s, string t) { int m = s.size(); int n = t.size(); if (m < n) return 0; vector<vector<long>>dp(m + 1, vector<long>(n + 1)); for (int i = 0; i <= m; i++) { dp[i][0] = 1; } for (int i = 1; i < m+1; i++) { for (int j = 1; j < n+1; 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[m][n]; }