30. Substring with Concatenation of All Words找出串联所有词的子串
题目:https://leetcode.com/problems/substring-with-concatenation-of-all-words/description/
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.
For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]
You should return the indices: [0,9]
.
(order does not matter).
找到索引,连续能匹配所有子串,(各子串匹配的顺序不考虑);
比如要匹配的子串集["foo", "bar"],那么母串是"barfoothefoobarman"时,返回[0,9]。
因为index = 0时有“barfoo”,index = 9时,有“foobar”
解决:
1、用到map结构(有点像hash)的counts,用来存放要匹配的子串s还有要匹配它的次数:counts( s ) = 要匹配的次数。
比如counts("bar") = 1,counts("foo") = 1;
2、从母串的第一位开始匹配(匹配成功或失败,第二次都从第二位开始,第三次从第三位。。即每次向后挪一位进行匹配):{
取长度len(每个word的长度)的字符串word{
看这个word是否在要匹配的counts中包含?
如果包含,进行seen(word)++,并判断seen(word)是否大于counts(word)。
如果不包含或子串出现次数大于要匹配的次数,break;
}接着紧挨着再取长度为len。。
}
class Solution { public: vector<int> findSubstring(string s, vector<string>& words) { unordered_map<string, int> counts; //string代表子串,int代表要匹配的word的个数 for (string word : words) counts[word]++; //某个word要匹配的个数 int n = s.length(), num = words.size(), len = words[0].length(); //n:母串长度,num:要匹配几个word,len:字串长度(每个word的长度相等) vector<int> indexes; //放入匹配的index for (int i = 0; i < n - num * len + 1; i++) { //从母串的第一个元素开始,每次挪一位匹配 unordered_map<string, int> seen; //seen记录word被包含的次数(不得大于要匹配的次数:counts中记录) int j = 0; for (; j < num; j++) {( string word = s.substr(i + j * len, len); //每次从母串截取长度len长度的字符串word,看是否是要匹配的word if (counts.find(word) != counts.end()) { //word是否在counts中找到 seen[word]++; // if (seen[word] > counts[word]) //匹配多余时要break(比如只要匹配一个abb,但是总共出现了两个abb就不对了) break; } else break; } if (j == num) indexes.push_back(i); //每个word都匹配好, } return indexes; } };
最笨的方法了。其他好方法可参见:https://leetcode.com/problems/substring-with-concatenation-of-all-words/discuss/