Substring with Concatenation of All Words (H)

题目

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:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
Input:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are "barfoo" 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: []

题意

给定一个字符串s和单词数组words,判断s中是否存在一个子串,正好为words中所有单词连起来的字符串(顺序不计)。

思路

暴力法:直接将每个单词看做是一个字符进行匹配,因为单词的顺序不一定,可以用HashMap来记录单词和出现次数的对应关系。

\(O(N)\)优化:暴力法的缺陷在于进行了大量的重复计算。参考 LeetCode 30. Substring with Concatenation of All Words 进行优化。

代码实现

Java

暴力

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        if (words.length == 0) {
            return new ArrayList<>();
        }
      
        int len = words[0].length(), num = words.length;
        List<Integer> list = new ArrayList<>();
        Map<String, Integer> record = new HashMap<>();
        Map<String, Integer> tmp = new HashMap<>();
      
        for (String word : words) {
            record.putIfAbsent(word, 0);
            record.put(word, record.get(word) + 1);
        }
      
        for (int i = 0; i < s.length(); i++) {
            if (s.length() - i < num * len) {
                break;
            }
          
						tmp.clear();
            int j = i;
          
            while (j - i != num * len) {
                String w = s.substring(j, j + len);
                if (!record.containsKey(w)) {
                    break;
                }
                tmp.putIfAbsent(w, 0);
                tmp.put(w, tmp.get(w) + 1);
                if (tmp.get(w) > record.get(w)) {
                    break;
                }
                j += len;
            }
          
            if (j - i == num * len) {
                list.add(i);
            }
        }
        return list;
    }
}

\(O(N)\)优化

class Solution {
    public List<Integer> findSubstring(String s, String[] words) {
        if (words.length == 0) {
            return new ArrayList<>();
        }
      
        int len = words[0].length(), num = words.length;
        List<Integer> list = new ArrayList<>();
        Map<String, Integer> record = new HashMap<>();
        Map<String, Integer> tmp = new HashMap<>();
      
        for (String word : words) {
            record.putIfAbsent(word, 0);
            record.put(word, record.get(word) + 1);
        }

        for (int i = 0; i < len && i < s.length(); i++) {
            if (s.length() - i < num * len) {
                break;
            }
          
            tmp.clear();
            int left = i, right = i;
          
            while (true) {
                if (right - left == num * len) {
                    list.add(left);
                    String headW = s.substring(left, left + len);
                    tmp.put(headW, record.get(headW) - 1);
                    left += len;
                }
              
                if (s.length() - left < num * len) {
                    break;
                }
              
                String w = s.substring(right, right + len);
              
                if (!record.containsKey(w)) {
                    tmp.clear();
                    left = right + len;
                } else {
                    tmp.putIfAbsent(w, 0);
                    tmp.put(w, tmp.get(w) + 1);
                    while (tmp.get(w) > record.get(w) && s.length() - left >= num * len) {
                        String headW = s.substring(left, left + len);
                        tmp.put(headW, tmp.get(headW) - 1);
                        left += len;
                    }
                }
              
                right += len;
            }
        }

        return list;
    }
}
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄