刷题——LeetCode 30. 串联所有单词的子串

30. 串联所有单词的子串

给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]

解释:
从索引 0 和 9 开始的子串分别是 “barfoo” 和 “foobar” 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解析:

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {

  /** 题目
   *给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s
   *中恰好可以由words中所有单词串联 形成的子串的起始位置。
   *注意子串要与words中的单词完全匹配,中间不能有其他字符 ,但不需要考 虑
   *words中单词串联的顺序。
   **/

  if (s.empty() || words.empty()) return {};

  vector<int> result;
  int word_len = words[0].size();
  int word_num = words.size();
  int all_len = word_len * word_num;

  //建立单词->单词个数的映射
  unordered_map<string, int> m1;
  for (const auto& w : words) m1[w]++;

  // 以不同的位置作为起始点
  for (int i = 0; i < word_len; ++i) {
    int left = i, right = i, words_count = 0;

    unordered_map<string, int> m2;

    // 双指针, 循环条件,保证有指针不超过字符串范围
    while (right + word_len <= s.size()) {
      string w = s.substr(right, word_len);
      right += word_len;

      if (m1.count(w) == 0) {
        // 目标字符不包括此字符,重置起始点
        words_count = 0;
        left = right;
        m2.clear();
      } else {
        m2[w]++;
        words_count++;
        while (m2.at(w) > m1.at(w)) {
          // 单词个数过多,移动左指针,直到个数正确
          string t_w = s.substr(left, word_len);
          words_count--;
          m2[t_w]--;
          left += word_len;
        }

        // 出口:找到符合条件的单词,位于左右指针之间
        if (words_count == word_num) result.push_back(left);
      }
    }
  }
  return result;
};

总结:

  1. 建立单词与单词个数的映射,以单词作为键值 巧妙应用 unordered_map
  2. 通过双指针实现窗口移动,保证字符匹配
  3. 匹配成功的条件就是,两个指针之间的单词个数达到与目标个数相同,每个单词出现的次数也相同。
  4. 以一个单词的不同位置作为起始点,可以实现所有单词的组合的比对。

你可能感兴趣的:(c++,leetcode,算法,动态规划)