方法一:填写bool数组
s[i]
和t[j]
相等,s[0~i
]是否是t[0~j]
的子序列,取决于s[0~i-1]
是否是t[0~j-1]
的子序列
s[i]
和t[j]
不相等,则s[0~i]
是否是t[0~j]
的子序列,取决于s[0~i]
是否是t[0~j-1]
的子序列
class Solution {
public:
bool isSubsequence(string s, string t) {
int m = s.size();
int n = t.size();
if(m == 0) return true;
if(m > n) return false;
vector<vector<bool>> dp(m, vector<bool>(n, false));
int pos = -1;
for (int j = 0; j < n; j++) {
if (t[j] == s[0]) {
dp[0][j] = true;
pos = j;
break;
}
}
if(pos != -1){
for (int j = pos + 1; j < n; j++) {
dp[0][j] = true;
}
}
for (int i = 1; i < m; i++) {
// 内层从i开始遍历,因为j < i时,s[0~i]肯定不是t[0~j]的子序列
for (int j = i; j < n; j++) {
// 最后一个字符相等,s[0~i]是否是t[0~j]的子序列,取决于s[0~i-1]是否是t[0~j-1]的子序列
if (s[i] == t[j]) dp[i][j] = dp[i - 1][j - 1];
// 最后一个字符不相等,则s[0~i]是否是t[0~j]的子序列,取决于s[0~i]是否是t[0~j-1]的子序列
else dp[i][j] = dp[i][j - 1];
}
}
return dp[m-1][n-1];
}
};
方法二:判断s和t的最长公共子序列长度
若s和t的最长公共子序列长度,就是s的长度,则说明s是t的子序列
class Solution {
public:
bool isSubsequence(string s, string t) {
int m = s.size();
int n = t.size();
// dp[i][j]:text1[0~i-1]和text2[0~j-1]最长公共自序列,不一定包含字符text1[i-1]和text2[j-1]
// 使用最后一个字符text1[i-1]和text2[j-1]时,可以不多申请一行一列
vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(s[i-1] == t[j-1]) dp[i][j] = dp[i-1][j-1] + 1;
else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
return dp[m][n] == s.size();
}
};
方法三:双指针
指向的字符相同,同时往后移动。不相同,则把tp往后移动
如果s是t的子序列,那最终sp一定指向\0
class Solution {
public:
bool isSubsequence(string s, string t) {
if(s.size() == 0) return true;
if(s.size() > t.size()) return false;
char* sp = &s[0];
char* tp = &t[0];
while(*sp && *tp){
if(*sp == *tp){
sp++;
}
tp++;
}
return *sp == '\0';
}
};