題目大意
判斷一個字符串s
是否是另一個串t
的子序列。子序列指將一個字符串刪除若干字符後組成的串。例如abc
是assdfbsc
的子序列。輸入限制:
- 0 <= s.length <= 100
- 0 <= t.length <= 10^4
- 兩個字符串都只包含小寫字母
進階:假如有超過10億個s
串,一個t
串,怎麼做會更好。
思路
對於一個s
和t
來說,可以直接從前往後判斷,考慮s
中的字符在t
中最早出現位置即可。但是假如s
數目較大的話,一個一個判斷就不能很好的利用t
只有一個的特性,因此可以利用最早出現位置的特性優化。
由於字符串中只包含小寫字母,而t.length <= 10^4
,因此可以打表記錄每個小寫字母的出現位置。流程如下:
有效起始位置 = -1
對i從0到1
判斷s[i]是否在 有效起始位置 後出現過 (二分查找)
未出現過 -> false
更新 有效起始位置 爲s[i]出現的位置
true
判斷是否出現過可以利用位置一定是從小到大的特性使用二分查找,對應STL中的upper_bound
。
另外就是邊界情況:
- s.size() = 0
- t.size() = 0
- 對於s[0],有效起始位置 應爲 -1
- s=aaaaaa,t=bbaaaa的情況(使用upper_bound而不是lower_bound)
代碼
class Solution {
public:
bool isSubsequence(string s, string t) {
if (s.size() <= 0)
return true;
const int sz = t.size();
if (sz <= 0)
return false;
vector<vector<int>> table(26);
for (int i = 0; i < sz; i++) {
table[t[i] - 'a'].push_back(i);
}
int laPos = -1;
for (size_t i = 0; i < s.size(); i++) {
const char sc = s[i];
const int sci = sc - 'a';
auto it = upper_bound(table[sci].begin(), table[sci].end(), laPos);
if (it == table[sci].end())
return false;
laPos = *it;
}
return true;
}
};
總結
打表+二分。