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: []
解题思路:
这道题可以用哈希表来记录每个单词的个数(因为有的test case里有重复的词语出现)
对map中的每一对键值对中的key,也就是单词,都有串联以他为开始的可能,所以我们针对这些可能性进行遍历。
我写了一个辅助函数进行判断以该位置开头的子串能否构成符合题目要求的子字符串:
因为给出的单词的长度都相同,所以我们可以直接取长度,然后判断该单词是否在map中:
1.若不在map中则无效,若在map中出现个数为0,也无效。
2.若在map中,出现个数大于0,则可以进行下一个单词的判断,不要忘记对map中的值进行修改辅助判断!
这里需要注意的是:
1.在对开头可能进行判断的循环中,start的递增幅度为start++,而不是start += wLen。
后者无法通过{"aa", "aa", "aa"} s = "aaaaaaaa"这个例子
2. 在辅助函数中,不要忘记对start进行递增操作,这里可以为 start += wLen
代码:
class Solution { public: vector<int> findSubstring(string s, vector<string>& words) { vector<int> ret; if(words.empty()) return ret; int num = words.size(); int wLen = words[0].size(); if(s.empty() || wLen > s.size() || (num * wLen > s.size())) return ret; unordered_map<string, int> wordTimes; //prevent repeat for(int i = 0; i < words.size(); i++){ wordTimes[words[i]]++; } for(auto wpair: wordTimes){ int start = 0; while(start > -1){ start = (int)s.find(wpair.first, start); if(start != -1){if(isValid(wordTimes, s, start, wLen, num)) ret.push_back(start); start ++; } } } return ret; } private: bool isValid(unordered_map<string, int> wordTimes, string str, int start, int wLen, int nums){ for(int i = 0; i < nums; i++){ if(start >= str.size()) return false; string tmp = str.substr(start, wLen); if(wordTimes.count(tmp) == 0 || wordTimes[tmp] == 0){ return false; } wordTimes[tmp]--; start += wLen; } return true; } };