这题用双指针做是O(m+n), 用动规是O(m * n)。只是练习。
dp[i][j]为s的[0,i-1]子串,为t的[0, j-1]的子串的子序列长度。 递推公式为, dp[i][j]在s[i-1] == t[j-1]时,为dp[i-1][j-1] + 1,否则为dp[i-1][j]与dp[i][j-1]的较大者。 剪枝操作是若dp[i][j]等于s的长度,就可以返回了。但先遍历s的话就没什么用。
class Solution {
public boolean isSubsequence(String s, String t) {
int[][] dp = new int[s.length() + 1][t.length() + 1];
for(int i=1; i<s.length() + 1; i++) {
char chars = s.charAt(i-1);
for(int j=1; j<t.length() + 1; j++) {
char chart = t.charAt(j-1);
if(chars == chart) {
dp[i][j] = dp[i-1][j-1] + 1;
}
else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
if(dp[i][j] == s.length()) {
return true;
}
}
}
return dp[s.length()][t.length()] == s.length();
}
}
这题定义dp数组为s的前i-1个元素,包含t的j-1个元素子序列的个数为dp[i][j]。 递推公式为: 当s[i-1] == t[j-1]时, dp[i][j]为dp[i-1][j-1] + dp[i-1][j],即为s不用最后一个s[i-1]做匹配,但使用倒数第二个元素做匹配的情形,加上s使用最后一个元素s[i-1]做匹配的情形。
当s[i-1] != t[j-1]时,dp[i][j]为dp[i-1][j],因为最后一个元素肯定不能进入当前匹配了,相当于删除的情形
初始化要注意,需要把dp[0-end][0]都初始化为1,意义就是s的[0,i]子串,含有一个空串t[0,0]的个数为1.
class Solution {
public int numDistinct(String s, String t) {
int[][] dp = new int[s.length() + 1][t.length() + 1];
for(int i=0; i<s.length()+1; i++) {
dp[i][0] = 1;
}
for(int i=1; i<=s.length(); i++) {
char chars = s.charAt(i-1);
for(int j=1; j<=t.length(); j++) {
char chart = t.charAt(j-1);
if(chars == chart) {
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
}
else {
dp[i][j] = dp[i-1][j];
}
}
}
return dp[s.length()][t.length()];
}
}