792. Number of Matching Subsequences
1. Description
Given a string s and an array of strings words, return the number of words[i] that is a subsequence of s.
A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
- For example, “ace” is a subsequence of “abcde”.
2. Example
Example 1:
Input: s = “abcde”, words = [“a”,“bb”,“acd”,“ace”]
Output: 3
Explanation: There are three strings in words that are a subsequence of s: “a”, “acd”, “ace”.
Example 2:
Input: s = “dsahjpjauf”, words = [“ahjpjau”,“ja”,“ahbwzgqnuk”,“tnmlanowax”]
Output: 2
3. Constraints
- 1 <= s.length <= 5 * $10^4$
- 1 <= words.length <= 5000
- 1 <= words[i].length <= 50
- s and words[i] consist of only lowercase English letters.
4. Solutions
Binary Search
m = words.size(), n = words[0].size(), o = str.size()
Time complexity: O(mlogo) // not related to n? because n is always less than o Space complexity: O(n)
class Solution {
public:
int numMatchingSubseq(const string &str, const vector<string> &words) {
unordered_map<char, vector<int>> letter_indices;
for (int i = 0; i < str.size(); ++i) {
letter_indices[str[i]].push_back(i);
}
int matching_count = 0;
for (const auto &word : words) {
if (word.size() > str.size()) {
continue;
}
unordered_map<char, int> letter_left_index;
int last_index = -1;
for (auto letter : word) {
auto it = upper_bound(
letter_indices[letter].begin() +
(letter_left_index.find(letter) == letter_left_index.end()
? 0
: letter_left_index[letter]),
letter_indices[letter].end(),
last_index);
if (it == letter_indices[letter].end()) {
goto pass;
} else {
letter_left_index[letter] = it - letter_indices[letter].begin();
last_index = *it;
}
}
++matching_count;
pass:;
}
return matching_count;
}
};