zoukankan      html  css  js  c++  java
  • [LeetCode] 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 = "wordgoodstudentgoodword",
      words = ["word","student"]
    Output: []

    给一个字符串和一单词列表,找出串联列表中所有单词的子串的起始位置。

    解法:也就是要求出串联所有单词的子串,然后返回起始位置的坐标。

    Java:

    class Solution {
        public List<Integer> findSubstring(String s, String[] words) {
            final Map<String, Integer> counts = new HashMap<>();
            for (final String word : words) {
                counts.put(word, counts.getOrDefault(word, 0) + 1);
            }
            final List<Integer> indexes = new ArrayList<>();
            final int n = s.length(), num = words.length, len = words[0].length();
            for (int i = 0; i < n - num * len + 1; i++) {
                final Map<String, Integer> seen = new HashMap<>();
                int j = 0;
                while (j < num) {
                    final String word = s.substring(i + j * len, i + (j + 1) * len);
                    if (counts.containsKey(word)) {
                        seen.put(word, seen.getOrDefault(word, 0) + 1);
                        if (seen.get(word) > counts.getOrDefault(word, 0)) {
                            break;
                        }
                    } else {
                        break;
                    }
                    j++;
                }
                if (j == num) {
                    indexes.add(i);
                }
            }
            return indexes;
        }
    }
    

    Python:

    class Solution(object):
        def findSubstring(self, s, words):
            """
            :type s: str
            :type words: List[str]
            :rtype: List[int]
            """
            result, m, n, k = [], len(s), len(words), len(words[0])
            if m < n*k:
                return result
    
            lookup = collections.defaultdict(int)
            for i in words:
                lookup[i] += 1                # Space: O(n * k)
    
            for i in xrange(k):               # Time:  O(k)
                left, count = i, 0
                tmp = collections.defaultdict(int)
                for j in xrange(i, m-k+1, k): # Time:  O(m / k)
                    s1 = s[j:j+k];            # Time:  O(k)
                    if s1 in lookup:
                        tmp[s1] += 1
                        if tmp[s1] <= lookup[s1]:
                            count += 1
                        else:
                            while tmp[s1] > lookup[s1]:
                                s2 = s[left:left+k]
                                tmp[s2] -= 1
                                if tmp[s2] < lookup[s2]:
                                    count -= 1
                                left += k
                        if count == n:
                            result.append(left)
                            tmp[s[left:left+k]] -= 1
                            count -= 1
                            left += k
                    else:
                        tmp = collections.defaultdict(int)
                        count = 0
                        left = j+k
            return resultv
    

    Python:

    # Time:  O(m * n * k), where m is string length, n is dictionary size, k is word length
    # Space: O(n * k)
    class Solution2(object):
        def findSubstring(self, s, words):
            """
            :type s: str
            :type words: List[str]
            :rtype: List[int]
            """
            result, m, n, k = [], len(s), len(words), len(words[0])
            if m < n*k:
                return result
    
            lookup = collections.defaultdict(int)
            for i in words:
                lookup[i] += 1                            # Space: O(n * k)
    
            for i in xrange(m+1-k*n):                     # Time: O(m)
                cur, j = collections.defaultdict(int), 0
                while j < n:                              # Time: O(n)
                    word = s[i+j*k:i+j*k+k]               # Time: O(k)
                    if word not in lookup:
                        break
                    cur[word] += 1
                    if cur[word] > lookup[word]:
                        break
                    j += 1
                if j == n:
                    result.append(i)
    
            return result
    

    C++:

    class Solution {
    public:
        vector<int> findSubstring(string s, vector<string>& words) {
            vector<int> res;
            if (s.empty() || words.empty()) return res;
            int n = words.size(), m = words[0].size();
            unordered_map<string, int> m1;
            for (auto &a : words) ++m1[a];
            for (int i = 0; i <= (int)s.size() - n * m; ++i) {
                unordered_map<string, int> m2;
                int j = 0; 
                for (j = 0; j < n; ++j) {
                    string t = s.substr(i + j * m, m);
                    if (m1.find(t) == m1.end()) break;
                    ++m2[t];
                    if (m2[t] > m1[t]) break;
                }
                if (j == n) res.push_back(i);
            }
            return res;
        }
    };
    

    C++:  

    class Solution {
    public:
        vector<int> findSubstring(string s, vector<string>& words) {
            if (s.empty() || words.empty()) return {};
            vector<int> res;
            int n = s.size(), cnt = words.size(), len = words[0].size();
            unordered_map<string, int> m1;
            for (string w : words) ++m1[w];
            for (int i = 0; i < len; ++i) {
                int left = i, count = 0;
                unordered_map<string, int> m2;
                for (int j = i; j <= n - len; j += len) {
                    string t = s.substr(j, len);
                    if (m1.count(t)) {
                        ++m2[t];
                        if (m2[t] <= m1[t]) {
                            ++count;
                        } else {
                            while (m2[t] > m1[t]) {
                                string t1 = s.substr(left, len);
                                --m2[t1];
                                if (m2[t1] < m1[t1]) --count;
                                left += len;
                            }
                        }
                        if (count == cnt) {
                            res.push_back(left);
                            --m2[s.substr(left, len)];
                            --count;
                            left += len;
                        }
                    } else {
                        m2.clear();
                        count = 0;
                        left = j + len;
                    }
                }
            }
            return res;
        }
    };
    

      

     

    All LeetCode Questions List 题目汇总

  • 相关阅读:
    第一部分 Linux的规划与安装
    第二部分 Linux 文件、目录与磁盘格式
    for in 遍历对象
    时间
    javaScript模块化
    Hbuilder将移动app或者web项目打包
    echarts的通用属性的介绍
    echart的x轴或y轴区间标签如何从大到小排列
    数组的sort()排序
    解决vscode下载很慢的问题
  • 原文地址:https://www.cnblogs.com/lightwindy/p/9667097.html
Copyright © 2011-2022 走看看