针对多个子序列存在性的判断 (LeetCode 792)

前言:对于两个字符串 s s s t t t,若要判断 t t t 是否是 s s s 的子序列,相信大家都不会陌生,一个 O ( n ) O(n) O(n) 的遍历或加上双指针的优化,都能很快地结束。但是,若要判断一系列字符串 w o r d s words words 中有几个是 s s s 的子序列呢?这时候就需要引入一个新的算法:滚动字典桶


  • 先来说一说 滚动字典桶 这个新名词:其实这个词是我自己发明的,主要有三个关键词:滚动 + 字典 + 桶。滚动是因为其不像字典树那样需要根据字符串的长度不断创建新节点,而是可以不断复用数组。字典是因为其构成与 字典树 有相似之处。桶是因为这种数据结构的本质是桶存储。

  • 可能上面的描述会让人一头雾水,那话不多说,先看题目和代码

class Solution {
public:

//PII 代表 {在 words 中的序号, 下一个待匹配字符}
using PII = pair<int, int>;

    int numMatchingSubseq(string s, vector<string>& words) {
        vector<vector<PII>> bucket(26);    

        int n = words.size();
        for(int i = 0; i < n; ++i){
            char c =  words[i][0];
            bucket[c - 'a'].push_back({i, 0});
        }

        int ans = 0;
        for(char c : s){
            vector<PII> old = bucket[c - 'a'];      // 倒出单词
            bucket[c - 'a'].clear();

            for(auto& [index, next] : old){
                string& t = words[index];
                next ++;

                if(next == t.size()){
                    ans ++;
                }else{
                    bucket[t[next] - 'a'].push_back({index, next});
                }
            }
        }
        return ans;
    }
};
  • 现在来解释一下整个序列匹配的过程,首先我们需要创建一个容量为 26 26 26 的桶, 0 0 0 25 25 25 分别对应字母 a − z a-z az,而第 i i i 个桶中存放的单词 正在等待匹配的下一个字母均为 c h a r ( ′ a ′ + i ) char('a'+i) char(a+i)
  • 在进行初始化后,开始对字符串 s s s 开始遍历,对于 s s s 中的每一个单词 c c c,便把 c c c 对应的桶中的所有单词 倒出,然后根据下一个待匹配的字符放进相应的桶。如果已经匹配到单词的最后一个字母,那么把答案加 1。
  • 时间复杂度: O ( s . l e n g t h + ∑ i = 1 n w o r d s [ i ] . l e n g t h ) O(s.length + \sum_{i = 1}^n words[i].length) O(s.length+i=1nwords[i].length)

以上就是 滚动字符桶 的全部内容了,大家可以类比字典树 (前缀树)来进行比较学习,这两个算法分别针对子序列和前缀有着非常优秀的时间复杂度!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值