30. Substring with Concatenation of All Words

You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.

Example 1:

Input:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoor" and "foobar" respectively.
The output order does not matter, returning [9,0] is fine too.

Example 2:

Input:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
Output: []

方法1: two pointers + hash

Cspiration: https://www.youtube.com/watch?v=L6NLra-rZoU

思路:

注意这道题里的几个restriction:

  1. 每个word的长度都一样
  2. word在一个instance当中不能使用超过words中的次数
  3. 词和词之间不能有间隔
  4. 顺序任意

用双指针的方法,就是如下的思路:左指针遍历每个位置,开始以右指针j为起点按照m = word.size()为单位检查substring是不是全部在words当中,而且次数吻合。如果有任意不吻合的情况,退出。只有当退出时发现k == 0, 说明n个单词都已经出现过了,才会将左指针i push到结果内。

易错点

  1. 虽然不明白为什么,但是(int)s.size这个typecase不做会出错

Complexity

Time complexity: O(l^2), l = s.size()
Space complexity: O(n * m)

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if (s.empty() || words.empty()) return {};
        vector<int> result;
        
        unordered_map<string, int> hash;
        for (auto w: words) hash[w]++;
        
        int n = words.size();
        int m = words[0].size();
        
        for (int i = 0; i <= (int)s.size() - m * n; i ++) {
            unordered_map<string, int> copy = hash;
            int k = n;
            int j = i;
            while (k > 0) {
                string cur = s.substr(j, m);
                if (copy[cur] <= 0) break;
                copy[cur]--;
                k--;
                j += m;
            }
            if (k == 0) result.push_back(i);
        }
        return result;
    }
};

方法2: sliding window

grandyang: https://www.cnblogs.com/grandyang/p/4521224.html
Code_Ganker: https://blog.csdn.net/linhuanmars/article/details/20342851?utm_source

思路:

Complexity

Time complexity: O(L), L = s.size()
Space complexity: O(m * n)

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if (s.empty() || words.empty()) return {};
        vector<int> result;
        
        unordered_map<string, int> hash;
        for (auto w: words) hash[w]++;
        int n = words.size();
        int m = words[0].size();
        
        for (int i = 0; i < m; i++) {
            unordered_map<string, int> curMap;
            int count = 0;
            int left = i;
            for (int j = i; j <= (int)s.size() - m; j += m) {
                string cur = s.substr(j , m);
                if (hash.count(cur)) {
                    curMap[cur]++;
                    if (curMap[cur] <= hash[cur]) {
                        count++;
                    } else {
                        while (curMap[cur] > hash[cur]) {
                            string t1 = s.substr(left, m);
                            curMap[t1]--;
                            if (curMap[t1] < hash[t1]) count --;
                            left += m;
                        }
                    }
                    
                    if (count == n) {
                        result.push_back(left);
                        curMap[s.substr(left, m)]--;
                        count --;
                        left += m;
                    }
                } else {
                    curMap.clear();
                    count = 0; 
                    left = j + m;
                }
                
            }
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值