438. Find All Anagrams in a String
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
Example 1:
Input:
s: "cbaebabacd" p: "abc"
Output:
[0, 6]
Explanation:
The substring with start index = 0 is "cba", which is an anagram of "abc".
The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input:
s: "abab" p: "ab"
Output:
[0, 1, 2]
Explanation:
The substring with start index = 0 is "ab", which is an anagram of "ab".
The substring with start index = 1 is "ba", which is an anagram of "ab".
The substring with start index = 2 is "ab", which is an anagram of "ab".
题目的意思是要求解在s中所有和p是'字谜'的子串。即子串中的字符和p相同,不考虑顺序。
通过对p创建哈希表map_target(key:字符, value:字符个数)。然后根据map_target的大小,记为count,即p中独特的字符个数在s中取子串。创建两个位置变量,begin和end,分别表示s中子串的起始位置和终止位置。
更新end的位置使得begin和end之间的子串包含p所需的所有字符,如果end-begin == p.size(),说明该子串是p的一个‘字谜’,返回此时begin所在的位置。
此时有个问题:begin和end怎么更新呢。
begin和end的更新主要是根据count的大小来判断。count表示还需要的独特的字符的个数,比如针对"ababa"中的字符'a',只有begin~end之间的map_target['a']的值等于0时,count才能减1。当count==0时,说明变量begin和end之间的子串已经包含p所需的所有字符,此时可以调整变量begin的位置,如果s[begin]不是目标p的字符,此时可以将变量begin往前移;如果s[begin]是目标p的字符,还要判断map_target[s[begin]]的大小,如果大小大于0了,说明begin到end之间的子串相对于目标p已经相差了字符s[begin]了,可以开始调整变量end的位置了,依此类推。
#include <iostream>
#include<vector>
#include<string>
#include<unordered_map>
using namespace std;
class Solution {
public:
vector<int> findAnagrams(string s, string p) {
vector<int> res;
unordered_map<char, int> target;
for (const auto & c : p)
target[c]++;
//注意,这个取的是target.size()作为判断条件,而不是p.size()。因为p中有可能有重复的元素。
int count = target.size();
size_t begin = 0;
size_t end = 0;
while (end < s.size())
{
char tmp = s[end];
if (target.find(tmp) != target.end())
{
target[tmp]--;
if (target[tmp] == 0)
count--;
}
end++;
//此时begin到end之间已经包含了p所需的所有字符。
while (count == 0)
{
char tmp = s[begin];
if (target.find(tmp) != target.end())
{
target[tmp]++;
if (target[tmp] > 0)
count++;
}
if (end - begin == p.size())
res.push_back(begin);
begin++;
}
}
return res;
}
};
int main()
{
Solution sln;
vector<int> res = sln.findAnagrams("cbaebabacd", "abc");
for (const auto &i : res)
cout << i << " ";
cout << endl;
std::cout << "Hello World!\n";
}