给定一个字符串S
和一个单词字典 words
,问, words
中一共有多少个单词words[i]
是字符串S
的子序列?
注意, 子序列不同于子串, 子序列不要求连续.
样例
样例 1:
输入: S = "abcde", words = ["a", "bb", "acd", "ace"]
输出: 3
解释: words内有三个单词是S的子串: "a", "acd", "ace".
样例 2:
输入: S = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
输出: 2
注意事项
- 所有
words
内的单词和S
只包含小写字母. S
的长度在[1, 50000]
范围内.words
的长度在[1, 5000]
范围内.words[i]
的长度在[1, 50]
范围内.
输入测试数据 (每行一个参数)如何理解测试数据?
class Solution {
public:
/**
* @param S: a string
* @param words: a dictionary of words
* @return: the number of words[i] that is a subsequence of S
*/
int numMatchingSubseq(string &S, vector<string> &words)
{
// Write your code here
int ret = 0;
map<char, vector<int>> mymap;
for(int i = 0; i < S.size(); i++)
{
mymap[S[i]].push_back(i);
}
for(auto it = mymap.begin(); it != mymap.end(); it++)
{
cout << it->first << " := " ;
for(int i = 0; i < (it->second).size(); i++)
cout << (it->second)[i] << " ";
cout << endl;
}
// vector<int> nums {2,3,6,7};
// cout << left_bound(nums,2) << endl;
for(int i = 0; i < words.size(); i++)
{
int pre = 0;
int j = 0;
for(; j < words[i].size(); j++)
{
if(mymap.count(words[i][j] == 0))
{
break;
}
int pos = left_bound(mymap[words[i][j]],pre);
if(pos == -1)
break;
pre = mymap[words[i][j]][pos] + 1;
}
if(j < words[i].size())
{
}
else
{
cout << words[i] << endl;
ret++;
}
}
// cout << left_bound(nums,7) << endl;
return ret;
}
// 利用二分来查找数组中元素的左边界,
// 如果没有这个元素的话就返回下一个更大元素的第一个下标
// 如果这个值比这个数组中的所有元素都要大的话就返回-1
int left_bound(vector<int>& nums, int target)
{
int lo = 0;
int hi = nums.size();
while(lo < hi)
{
int mid = lo + (hi - lo)/2;
if(target > nums[mid])
{
lo = mid + 1;
}
else
{
hi = mid;
}
}
return (lo == nums.size()) ? -1 : lo;
}
};