LeetCode438. Find All Anagrams in a String

版权声明:本文为博主原创文章,欢迎转载!转载请保留原博客地址。 https://blog.csdn.net/grllery/article/details/85269697

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的位置了,依此类推。

参考https://leetcode.com/problems/find-all-anagrams-in-a-string/discuss/92007/Sliding-Window-algorithm-template-to-solve-all-the-Leetcode-substring-search-problem

https://github.com/abesft/leetcode/blob/master/438FindAllAnagramsInString/438FindAllAnagramsInString.cpp

#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";
}

猜你喜欢

转载自blog.csdn.net/grllery/article/details/85269697
今日推荐