1. 题意
判断字符串 s s s是否为 t t t的子序列
2. 题解
2.1 双指针
对于在 t t t中找到的 s [ i ] s[i] s[i]字符,我们只需要找下一个即可。
即一个指针 i i i指向 s s s,一个指针 j j j指向 t t t;
- s [ i ] = = t [ j ] , i ← i + 1 , j ← j + 1 s[i] ==t[j], i \leftarrow i+1,j \leftarrow j+1 s[i]==t[j],i←i+1,j←j+1
- s [ i ] ≠ t [ j ] , i ← i + 1 s[i] \ne t[j], i \leftarrow i+1 s[i]=t[j],i←i+1
代码
class Solution {
public:
bool isSubsequence(string s, string t) {
int slen = s.size();
int tlen = t.size();
if ( slen > tlen)
return false;
int i = 0;
int j = 0;
while ( i < slen && j < tlen ) {
if (s[i] == t[j])
++i,++j;
else {
++j;
}
}
return i == slen;
}
};
2.2 双指针+预处理
我们可以预处理 j j j,当 s [ i ] ≠ t [ j ] s[i]\ne t[j] s[i]=t[j], j j j跳到下一个邻近 s [ i ] s[i] s[i]表示字符出现的位置。
预处理我们可以从后往前遍历;得到转移方程
d p [ i ] [ j ] = { d p [ i + 1 ] [ j ] , c = = ′ a ′ + j i , c ≠ ′ a ′ + j dp[i][j]= \begin{cases} dp[i+1][j], \quad c == 'a'+j\\ i, \quad c \ne 'a'+j \end{cases} dp[i][j]={dp[i+1][j],c==′a′+ji,c=′a′+j
d p [ i ] [ j ] dp[i][j] dp[i][j]表示在字符串 t t t中的 i i i位置与其右端最邻近的 j + ′ a ′ j +'a' j+′a′字符的位置。
这个dp
数组的作用,是来加速上面双指针中
j
j
j指针的跳转。
class Solution {
public:
bool isSubsequence(string s, string t) {
int n = s.size();
int m = t.size();
vector<vector<int>> dp(m + 1, vector<int>(26, m));
for (int i = m - 1; ~i ; --i) {
for (int j = 0;j < 26; ++j) {
if ( j + 'a' == t[i]) {
dp[i][j] = i;
}
else {
dp[i][j] = dp[i + 1][j];
}
}
}
int i = 0;
int j = 0;
while (i < n && j < m) {
if (s[i] == t[j]) {
i++;j++;
}
else {
j = dp[j][s[i] - 'a'];
}
}
return i == n;
}
};
2.3 动态规划
可以转换为经典的 L C S ( l o n g e s t c o m m o n s e q u e n c e ) LCS(longest\ common\ sequence) LCS(longest common sequence)最长公共子序列问题,
即 L C S ( s , t ) = s . s i z e ( ) LCS(s,t) =s.size() LCS(s,t)=s.size()
class Solution {
public:
bool isSubsequence(string s, string t) {
if (s.empty())
return true;
int m = static_cast<int>( s.size() );
int n = static_cast<int>( t.size() );
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][j - 1], dp[i - 1][j]);
}
}
return dp[m][n] == m;
}
};