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 = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
Output: []
思路一:
1.把每一个子串送给一个判别函数进行判断,同时用vector<bool>去标记每一个words的受访问状态,也即在一次外层判断中,一个子串只能访问words的单词一次。
2.终止条件,如果剩余的子串长度小于words中字符串总长度,则一定找不到了,停止查找
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
if(words.empty()||s.empty())
return {};
int wsz=words.size();
int cnt=0;
vector<int> result;
for(int j=0;j<=int(s.size())-int(words[0].size())*wsz;j++)
{
vector<bool> state(wsz,true);
for(int i=0;i<words[0].size()*wsz;)//终止条件
{
bool flag=inWords(s.substr(j+i,words[0].size()),words,state);//判断子串
if(flag)
{
cnt++;//统计匹配次数
if(cnt==wsz)//words所有单词都已成功匹配
{
cnt=0;
result.push_back(j);//记录索引
break;
}
i=i+words[0].size();//判断下一个同等长度的单词是否出现在words中
}
else {
cnt = 0;//如果存在一个匹配不上,则统计清零,重新开始
break;
}
}
}
return result;
}
//判断子串是否存在words中,用state来统计受匹配次数,不能重复匹配
bool inWords(string s,vector<string>& words,vector<bool>& state)
{
for(int i=0;i<words.size();i++)
{
if(words[i]==s&&state[i])
{
state[i]=false;
return true;
}
}
return false;
}
};
思路简单,但是时间复杂度太高,而且没有考虑到words内单词重复的情况,用哈希表既可以统一考虑单词重复的情形,也可以免除vector<bool>统计状态带来的麻烦:
思路二:用哈希表存储单词及其被允许匹配的次数
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> result;
if (s.empty()||words.empty())
return result;
int m = words.size(), n = words[0].size();
unordered_map<string,int> map1;//存储word及其次数
for(auto& w:words)
++map1[w];
for(int i=0;i<=int(s.size())-m*n;i++)
{
unordered_map<string,int> map2;
int j=0;
for(;j<m;j++)
{
string str=s.substr(i+j*n,n);
if(map1.find(str)==map1.end())
break;//没找到
++map2[str];//匹配成功
if(map2[str]>map1[str])//超过匹配次数
break;
}
if(j==m)
result.push_back(i);
}
return result;
}
};