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

来源:互联网 发布:c语言if else嵌套 编辑:程序博客网 时间:2024/05/19 19:32


题目链接: 

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 中是固定且有限的 ;




代码如下:

class Solution {public:    vector<int> findSubstring(string s, vector<string>& words) {        vector<int> ret;        auto wordLength = words.front().size();        if (s.size() < wordLength*words.size()) { return ret; }        unordered_map<string, int> existedWords;        for (auto w : words) {            existedWords[w]++;        }        for (size_t i = 0; i <= s.size() - wordLength; i++) {            bool match = true;            unordered_map<string, int> matchedWords;            for (auto j = i; j < i + wordLength * words.size(); j += wordLength) {                auto word = s.substr(j, wordLength);                if (existedWords[word] < 1 ||                     matchedWords[word] >= existedWords[word]) {                    match = false;                    break;                }                matchedWords[word]++;            }            if (match) {                ret.push_back(i);            }        }        return ret;    }};




Runtime: 256 ms


阅读全文
0 0
原创粉丝点击