暴力解法
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
if(s.length() == 0 || words.size() == 0)
{
return {};
}
if(s.length() < words.size()*words[0].length())
{
return {};
}
vector<int> result;
unordered_map<string, int> mp, tmp;
string str = "";
for (auto str : words) {
++mp[str];
}
int i = 0;
int j = 0;
for(i = 0; i <= s.size()-words.size()*words[0].length(); i++)
{
for(j = i; j < i+words.size()*words[0].length(); j+=words[0].length())
{
str = s.substr(j, words[0].length());
if (mp.find(str) == mp.end())
{
break;
}
++tmp[str];
}
if (j == i + words.size()*words[0].length() && tmp == mp)
{
result.push_back(i);
}
tmp.clear();
}
return result;
}
};
滑动窗口,窗口的初始长度为单个单词word的长度,left和right表示窗口的开始和结束,每次加入word长度的单词,但窗口长度与所有子串的长度和相等时,匹配成功。
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
if(s.length() == 0 || words.size() == 0)
{
return {};
}
if(s.length() < words.size()*words[0].length())
{
return {};
}
vector<int> result;
unordered_map<string, int> mp, tmp;
string str = "";
for (auto str : words) {
++mp[str];
}
for(int i = 0; i < words[0].length(); i++)
{
int left = i;
int right = i;
while(right <= s.length()-words[0].length())
{
str = s.substr(right, words[0].length());
if (mp.find(str) == mp.end())
{
right += words[0].length();
left = right;
tmp.clear();
continue;
}
++tmp[str];
while(tmp[str] > mp[str])
{
string temp = s.substr(left, words[0].length());
if(tmp[temp] == 1)
{
for(auto it=tmp.begin(); it!=tmp.end(); )
{
if(it->first == temp)
{
it = tmp.erase(it);
}
else
{
++it;
}
}
//auto iter = std::remove(std::begin(tmp), std::end(tmp), temp);
//tmp.remove(temp);
}
else
{
tmp[temp]--;
}
left += words[0].length();
}
right += words[0].length();
if (right == left + words.size()*words[0].length())
{
result.push_back(left);
}
}
tmp.clear();
}
return result;
}
};
可以看到区别在于外层循环只需要每个子串的长度,且循环内部加了某个单词的出现次数大于期望次数的处理。