题目链接:https://leetcode.com/problems/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 wordsexactly once and without any intervening characters.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
思路:和Longest Palindromic Substring 还有 Minimum Window Substring 是一个类型的题目。所以我们要把字典中的单词映射到一个hash table中去,还需要一个辅助hash table和一个计数器来记录当前已经找到的单词和他的数目。刚开始考虑了很多种情况,发现情况越考虑越多,错了几次之后就不想管了,按照一个最简洁的思路来实现。
同样设置一个左右指针来维护一个窗口,每次操作有两种情况:
1. 如果当前子串在字典中,并且数目也不超过字典中的数目,则右指针滑动一个单词的大小继续寻找下一个单词
2. 如果当前子串不在字典中,或者超出了字典中此单词的数量,那么left指针向右滑动一位,同时右指针也滑动到和左指针相同的位置重新开始计算。
这种方法简直是简单粗暴,哈哈,最终我还是打败了3%的程序,成功A掉了这题,那就这样吧!
时间复杂度大概是O(n*n),空间复杂度为O(n)。
代码如下:
class Solution { public: vector<int> findSubstring(string s, vector<string>& words) { vector<int> result; if(s.size() == 0 || words.size() == 0) return result; int left =0, right = 0, find =0; unordered_map<string, int> hash; unordered_map<string, int> strState; for(int i = 0; i< (int)words.size(); i++) hash[words[i]]++; while(right < (int)s.size()) { string tem = s.substr(right, words[0].size()); if(hash.find(tem) != hash.end() && (strState.find(tem) == strState.end() || strState[tem] < hash[tem])) { //第一次出现,则为1,否则计数加1 strState[tem] = (strState.find(tem)==strState.end())?1:(strState[tem]+1); find++; //找到了所有的单词,则保存结果,并且情况计数器,左指针向右滑动一位,重新开始计数 if(find == (int)words.size()) { result.push_back(left); strState.clear(); left++; right = left; find = 0; } else//当前单词在字典中,但是还没有将字典中的单词全部找到,则右指针滑动一个单词的长度 right += words[0].size(); } else//如果当前的单词不在字典中,或者超出了字典中此单词的数量,则左指针向右滑动一位重新开始计数 { strState.clear(); find = 0; left++; right = left; } } return result; } };