题目
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).
Example 1:
s = "abc"
, t = "ahbgdc"
Return true
.
Example 2:
s = "axc"
, t = "ahbgdc"
Return false
.
Follow up:
If there are lots of incoming S, say S1, S2, … , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?
思路一:双指针
- 采用双指针遍历整个字符串 t 判断 s 是否为字串。
bool isSubsequence(string s, string t) {
int i=0,j=0;
while(j<t.size()&&i<s.size())
{
if(s[i]==t[j]){i++;j++;}
else j++;
}
return i==s.size();
}
代码十分简单,但是效率不高,而且没有用到DP相关知识。
思路二:DP
-
采用动态规划,
dp[i][j]
表示 字符串 s 与 t 的最长公共子串的长度,则当dp[s.length()-1][t.length()-1]==s.length()
时,s 是 t 的字串,否则不是。接下来就是推导求最长公共子串的状态转移方程,
- 当
s[i]==t[j]
时,dp[i][j]==dp[i-1][j-1]+1
- 当
s[i]!=t[j]
时,dp[i][j]==dp[i-1][j-1]
由此我们可以写出代码
- 当
bool isSubsequence(string s, string t) {
int ss=s.size(),tt=t.size();
int dp[2][tt+1];
memset(dp,0,sizeof(dp));
int i = 1,j = 1;
for(i=1;i<=ss;i++)
{
for(j=1;j<=tt;j++)
{
dp[i%2][j]=s[i-1]==t[j-1]?dp[(i-1)%2][(j-1)]+1:max(dp[i%2][(j-1)],dp[(i-1)%2][j]);
}
}
return dp[ss%2][tt]==ss;
}
强行写出了DP的代码,同时优化了空间复杂度到2n(否则有样例爆栈)
但是我们发现这样消耗的时间比第一次的代码多,实际效果并不如第一次的好。