LeetCode 匹配子序列的单词数(upper_bound库函数)

给定字符串 S 和单词字典 words, 求 words[i] 中是 S 的子序列的单词个数。

示例:

输入: 
S = "abcde"
words = ["a", "bb", "acd", "ace"]
输出: 3
解释: 有三个是 S 的子序列的单词: "a", "acd", "ace"。

注意:

所有在words和 S 里的单词都只由小写字母组成。
S 的长度在 [1, 50000]。
words 的长度在 [1, 5000]。
words[i]的长度在[1, 50]。

思 路 分 析 : \color{blue}思路分析: 刚开始吧,可能大家都想着直接暴力匹配,蛋式S串的长度比较长时,耗时还大了。所以我们得绞尽脑汁对S串进行一些预处理,首先我想到的方法是首先从左到右、从右到左扫描一遍S串,确定每个字母第一次出现的下标、最后一次出现的下标,在我们匹配word的时候,可以先确定匹配的长度范围为[word[0]第一次出现的下标,word.back()最后一次出现的下标],从而到达缩小匹配单词的长度。

class Solution {
public:
    int numMatchingSubseq(string S, vector<string>& words) {
        int resCount = 0, strSize = S.size();
        vector<int> firstIndex(26, strSize - 1), lastIndex(26, 0);
        //从左到右扫描S串,确定每个字符最后一次出现的下标
        for (int index = 0; index < strSize; ++index){
            lastIndex[S[index] - 'a'] = index;
        }
        //从右到左扫描S串,确定每个字符第一次出现的下标
        for (int index = strSize - 1; index >= 0; --index){
            firstIndex[S[index] - 'a'] = index;
        }
        //开始匹配字符串
        for (auto &word : words){
            //scanIndex为word[0]第一次出现的下标,endIndex为word.back()最后一次出现的下标
            int wordSize = word.size(), wordIndex = 0, scanIndex = firstIndex[word[0] - 'a'], endIndex = lastIndex[word[wordSize - 1] - 'a'];
            while (scanIndex <= endIndex && wordIndex < wordSize){//从这个区间段开始匹配word
                if (S[scanIndex++] == word[wordIndex]){
                    wordIndex += 1;
                }
            }
            if (wordIndex == wordSize){//如果成功匹配
                resCount += 1;
            }
        }
        return resCount;
    }
};

LeetCode 匹配子序列的单词数(upper_bound库函数)_第1张图片
优化方法二:我们使用二维vector容器统计S串中各个字符出现的下标,并且是从左到右扫描S串,这样在容器中各个字符出现的下标都是递增的,这时我们就可以借助upper_bound库函数进行帮助查找。

upper_bound函数是在一个有序的序列中寻找第一个不小target的迭代器。
class Solution {
public:
    int numMatchingSubseq(string S, vector<string>& words) {
        int resCount = 0, strSize = S.size();
        vector<vector<int>> chIndexs(26);
        //从左到右扫描S串,统计每个字符出现的下标
        for (int index = 0; index < strSize; ++index){
            chIndexs[S[index] - 'a'].push_back(index);
        }
        //开始匹配字符串
        for (const auto &word : words){
            int nowIndex = -1, flag = 1;//nowIndex为匹配完上一个字符需要的最小下标
            for (const auto &ch : word){
                //在S串中寻找匹配ch的最小下标(这个下标出现在chIndexs[ch - 'a']中,还必须的在上一个字符需要的最小下标nowIndex之后)
                auto it = upper_bound(chIndexs[ch - 'a'].begin(), chIndexs[ch - 'a'].end(), nowIndex);
                if (it == chIndexs[ch - 'a'].end()){//没有找到,退出循环
                    flag = 0;
                    break;
                }
                else{
                    nowIndex = *it;//更新匹配完上一个字符需要的最小下标
                }
            }
            if (flag){//如果成功匹配
                resCount += 1;
            }
        }
        return resCount;
    }
};

LeetCode 匹配子序列的单词数(upper_bound库函数)_第2张图片

你可能感兴趣的:(LeetCode,字符串)