题目
Given a string s and a string t, check if s is subsequence of t.
You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).
A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, “ace” is a subsequence of “abcde” while “aec” is not).
意思就是判断一个字符串是不是另一个字符串的子序列(即不用连续)
算法思路
这题最直接的做法就是直接把字符串t遍历一遍,看字符串s的字符是否按顺序出现,算法时间复杂度是O(n),实现如下
class Solution {
public:
bool isSubsequence(string s, string t) {
int n1 = s.size(), n2 = t.size();
int k = 0;
for(int i=0; i<n2; ++i){
if(s[k]==t[i]) k++;
}
if(k == n1) return true;
else return false;
}
};
另外一个做法是使用动态规划思想,用一个二维数组布尔f[i][j]为true表示字符串s的前i个字符是字符串t的前j个字符的子序列,这样我们可以知道f[0][j]为true,f[i][0]为false,f[i][j]为true就两种情况,一是t的前j-1个已经包含了s的前i个,二是t的前j-1个包含了s的前i-1个且s第i个和t第j个相等,即f[i][j] = f[i][j-1] || f[i-1][j-1]&&s[i-1]==t[j-1] 。最后的结果就是f[n][m],n是s的长度,m是t的长度。 我们可以看出来f[i][j]依赖于f[i-1][j]和f[i-1][j-1],所以为了节省空间,i可以只用0/1表示。该算法时间复杂度为O(mXn),具体实现如下
class Solution {
public:
bool isSubsequence(string s, string t) {
int n,m,k,i,j;
n = s.size();
m = t.size();
for(i=0; i<=m; ++i) f[0][i] = true;
for(k=i=1; i<=n; ++i, k=1-k){
f[k][0] = false;
for(j=1;j<=m; ++j)
f[k][j] = f[k][j-1]||f[1-k][j-1]&&s[i-1]==t[j-1];
}
return f[1-k][m];
}
private:
bool f[2][600000];
};
显然本题使用最直接的算法能得到更好的效率而且更加简单,所以不要盲目地去使用动态规划