https://leetcode.com/problems/find-all-anagrams-in-a-string/description/
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".
- 字符串题。弄清楚Sliding Window algorithm之后简单。
- 首先对string p做hash。假设在string s上有一个window,如果匹配一个hash[i],就对-- hash[i]的话,最终结果就是要找到一个window宽度为p.size(),同时所有hash[i]都为0,即所有字符都匹配。
- 基于这个思想,我们可以观察到
- the sum of all hash[i] is always >=0;
- count is the sum of all positive hash[i];
- therefore, every hash[i] is zero if and only if count is 0.
- 有了这个原则后,我们可以用两个指针指向window的left和right,count初始为p.size(),实际上是sum(hash[i])。然后开始移动right来扩展window,如果匹配,则-- count,然后继续移动right去扩展window。同时-- hash[right],即对当前window中的char的hash值进行修改。
- 如果window的宽度为p.size(),即right - left == p.size(),那么判断如果count == 0则代表所有hash[i]已经匹配了,也就是找到匹配的anagram了。然后把window向右移动,即++ left。同时如果原先s[left]是存在于p中的,即hash[left] >= 0,则++ count复原。同时原先left处的字符已经不在当前window里了,则++ hash[left]来复原。
- 算法里注意对right指针对应的char的操作都是--,对left指针的则是++。对right指针进行的修改,在left移出window时会都复原,这样可以保证每个window初始时值都是一样。
- Find All Anagrams in a String - LeetCode

1 // 2 // main.cpp 3 // LeetCode 4 // 5 // Created by Hao on 2017/3/16. 6 // Copyright © 2017年 Hao. All rights reserved. 7 // 8 9 #include <iostream> 10 #include <vector> 11 #include <unordered_map> 12 using namespace std; 13 14 class Solution { 15 public: 16 vector<int> findAnagrams(string s, string p) { 17 vector<int> vResult; 18 19 // corner case 20 if (s.empty() || p.empty() || s.size() < p.size()) return vResult; 21 22 unordered_map<char, int> hash; 23 24 // hash chars in p 25 for (auto ch : p) 26 ++ hash[ch]; 27 28 // two points indicating the begin/end of the window 29 // count actually means the sum of all positive hash[i], and the sum of all hash[i] is always >= 0 30 int left = 0, right = 0, count = p.size(); 31 32 while (right < s.size()) { 33 // move window's right point rightward, if the char exists in p, decrease the count 34 if (hash[s.at(right)] > 0) 35 -- count; 36 37 -- hash[s.at(right)]; 38 39 ++ right; 40 41 // if the window's width == p.size(), then we have to slide window rightward for a new window, move the left point rightward 42 if (right - left == p.size()) { 43 // count == 0 if and only if every hash[i] == 0, means we find the anagram 44 if (0 == count) 45 vResult.push_back(left); 46 47 // Only increase the count if the char exists in p 48 if (hash[s.at(left)] >= 0) 49 ++ count; 50 51 ++ hash[s.at(left)]; 52 53 ++ left; 54 } 55 } 56 57 return vResult; 58 } 59 }; 60 61 int main(int argc, char* argv[]) 62 { 63 Solution testSolution; 64 65 vector<string> iVec = {"cbaebabacd", "abc", "abab", "ab"}; 66 vector<int> result; 67 68 /* 69 0 6 70 0 1 2 71 */ 72 for (int i = 0; i < iVec.size() - 1; i += 2) { 73 result = testSolution.findAnagrams(iVec[i], iVec[i + 1]); 74 75 for (auto it : result) 76 cout << it << " "; 77 cout << endl; 78 } 79 80 return 0; 81 }