当前位置:   article > 正文

[算法分析与设计] leetcode 每周一题: 030. Substring with Concatenation of All Words

[算法分析与设计] leetcode 每周一题: 030. Substring with Concatenation of All Words


题目链接: 

30. Substring with Concatenation of All Words




题目大意:
给定字符串 s 和单词列表 words (其中所有 word 为等长字符串, 可以重复), 找出字符串 s 的 所有满足条件的子串的首字符的索引(index) ; 其中, 所有子串的内容均为 words 中所有 word 首尾连结而成的(顺序随意), 且所有单词均出现且仅完整出现一次 ;


例如: 给定 s: "barfoothefoobarman", words: ["foo", "bar"], 则输出可以是: [0, 9]




解题过程:

(1) 考虑所有单词(word) 等长且必须在目标子串中互相首尾相连(故而 目标子串长度恒定), 故可以在遍历字符串 s 时不断进行逐词的检查(分别从每个下标), 一旦发现不符合要求立即转而开始从下一个字符开始进行检查 ;

(2) 一开始没有想到 words 中允许重复, 所以直接用 unordered_set 作处理, 后来发现重复的存在后就改用 unordered_multiset, 但这样便导致了超时, 所以还是要老老实实用 unordered_map (直接记录每个词的重复个数) ;


(*) 其实, 既然已经确定 "所有单词(word) 等长且必须在目标子串中互相首尾相连", 那么应该可以直接对 输入字符串 s 做逐词的检查, 也即 以词长为步进, (我这里就只是先逐个索引地遍历再(针对)每一次作处理, 显然有很多冗余检查), 因为目标子串所在的 "轨迹" 在 s 中是固定且有限的 ;




代码如下:

  1. class Solution {
  2. public:
  3. vector<int> findSubstring(string s, vector<string>& words) {
  4. vector<int> ret;
  5. auto wordLength = words.front().size();
  6. if (s.size() < wordLength*words.size()) { return ret; }
  7. unordered_map<string, int> existedWords;
  8. for (auto w : words) {
  9. existedWords[w]++;
  10. }
  11. for (size_t i = 0; i <= s.size() - wordLength; i++) {
  12. bool match = true;
  13. unordered_map<string, int> matchedWords;
  14. for (auto j = i; j < i + wordLength * words.size(); j += wordLength) {
  15. auto word = s.substr(j, wordLength);
  16. if (existedWords[word] < 1 ||
  17. matchedWords[word] >= existedWords[word]) {
  18. match = false;
  19. break;
  20. }
  21. matchedWords[word]++;
  22. }
  23. if (match) {
  24. ret.push_back(i);
  25. }
  26. }
  27. return ret;
  28. }
  29. };




Runtime: 256 ms


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/252585?site
推荐阅读
相关标签
  

闽ICP备14008679号