- 串联所有单词的子串
给定一个字符串 s 和一些 长度相同 的单词 words 。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符 ,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:s = “barfoothefoobarman”, words = [“foo”,“bar”]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 “barfoo” 和 “foobar” 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:s = “wordgoodgoodgoodbestword”, words = [“word”,“good”,“best”,“word”]
输出:[]
示例 3:
输入:s = “barfoofoobarthefoobarman”, words = [“bar”,“foo”,“the”]
输出:[6,9,12]
提示:
1 <= s.length <= 104
s 由小写英文字母组成
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i] 由小写英文字母组成
//总体思路:用两个unordered_map<string,int>解决查找问题。
//首先用unordered_map<string,int> research保存需要查找的字符串words,因为words可能有重复,所以采用unordered_map<string,int>保存数量
//然后从字符串首位开始查找,到n-m*len+1前截至,因为后面的都不够截取的数量,不用再查找了。
//因为每个word的长度相等,所以每次截取相同长度len的字符串,然后去research中查找,如果找不到,直接跳出。如果找到了,就把他存入临时的unordered_map<string,int> map中,并且数量加1,然后与research中的数量比较,如果大于,就跳出。全部比较完后,如果j==m,说明挨个都比较了,说明符合我们的要求,就存入ret中
//总体思路:用两个unordered_map<string,int>解决查找问题。
//首先用unordered_map<string,int> research保存需要查找的字符串words,因为words可能有重复,所以采用unordered_map<string,int>保存数量
//然后从字符串首位开始查找,到n-m*len+1前截至,因为后面的都不够截取的数量,不用再查找了。
//因为每个word的长度相等,所以每次截取相同长度len的字符串,然后去research中查找,如果找不到,直接跳出。如果找到了,就把他存入临时的unordered_map<string,int> map中,并且数量加1,然后与research中的数量比较,如果大于,就跳出。全部比较完后,如果j==m,说明挨个都比较了,说明符合我们的要求,就存入ret中
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> ret;
unordered_map<string,int> research;
for(int i=0;i<words.size();i++)
{
research[words[i]]++;
}
int n=s.size();
int m=words.size();
int len=words[0].size();
for(int i=0;i<n-m*len+1;i++)
{
unordered_map<string,int> map;
int j;
for(j=0;j<m;j++)
{
if(research.find(s.substr(i+j*len,len))==research.end())
break;
if(++map[s.substr(i+j*len,len)]>research[s.substr(i+j*len,len)])
break;
}
if(j==m)
ret.push_back(i);
}
return ret;
}
};
总体思路:暴力的方法,样例没有全部通过,通过了151/176.暴力的思路简单,如下。
//第一步:采用回溯法,排列的模板将words全排列后存入result中,然后把result连接成ans
//第二步:采用字符串匹配的方式,匹配,把匹配到的放入ret中
//第三步:对ret进行排序,去重操作,返回ret
//总体思路:暴力的方法,样例没有全部通过,通过了151/176.暴力的思路简单,如下。
//第一步:采用回溯法,排列的模板将words全排列后存入result中,然后把result连接成ans
//第二步:采用字符串匹配的方式,匹配,把匹配到的放入ret中
//第三步:对ret进行排序,去重操作,返回ret
class Solution {
private:
vector<vector<string>> result;
vector<string> path;
void BackTracking(vector<string>& words,vector<bool>& used)
{
if(path.size()==words.size())
{
result.push_back(path);
return;
}
for(int i=0;i<words.size();i++)
{
if(used[i])
continue;
path.push_back(words[i]);
used[i]=true;
BackTracking(words,used);
path.pop_back();
used[i]=false;
}
}
vector<string> ans;
void lianjie(vector<vector<string>>& result)
{
for(int i=0;i<result.size();i++)
{
string str;
for(int j=0;j<result[i].size();j++)
{
str+=result[i][j];
}
ans.push_back(str);
}
}
vector<int> ret;
void pipei(string s,string a)
{
for(int i=0;i<s.size();i++)
{
int index;
if(s[i]==a[0])
{
index=i;
int j;
for(j=0;j<a.size();j++)
{
if(s[i]==a[j])
{
i++;
}
else
{
break;
}
}
if(j==a.size())
{
ret.push_back(index);
}
i=index;
}
}
}
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<bool> used(words.size(),false);
BackTracking(words,used);
lianjie(result);
for(int i=0;i<ans.size();i++)
{
cout<<ans[i]<<endl;
}
for(int i=0;i<ans.size();i++)
{
pipei(s,ans[i]);
}
sort(ret.begin(),ret.end());
vector<int>::iterator new_end;
new_end=unique(ret.begin(),ret.end());
ret.erase(new_end,ret.end());
return ret;
}
};