给定一个字符串 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"]
输出:[]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
typedef unsigned long long ull;
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
if(words.empty() || words.size()*words[0].size() > s.size())
return {};
int i, j, wlen = words[0].size(), n = words.size();
unordered_map<ull,int> m;
for(auto& w : words)
{
ull v = 0;
for(char ch : w)
v = v*128+ch;
m[v]++;//字符转成128进制的数,计数
}
//字符串s每个位置开始后的wlen个字符的ull表示
vector<ull> hashv(s.size(),0);
ull pown = 1;
for(i = 0; i < wlen; ++i)
{
pown *= 128;
hashv[0] = hashv[0]*128+s[i];
}
for(i = 1; i <= s.size()-wlen; ++i)
{
hashv[i] = hashv[i-1]*128-s[i-1]*pown+s[i+wlen-1];
}
vector<int> ans;
bool ok;
for(i = 0; i <= s.size()-n*wlen; ++i)
{
unordered_map<ull, int> temp(m);
ok = true;
for(j = i; j < n*wlen+i; j+=wlen)
{
if(--temp[hashv[j]] < 0)
{
ok = false;
break;
}
}
if(ok) ans.push_back(i);
}
return ans;
}
};
584 ms 126.6 MB