LeetCode 438. Find All Anagrams in a String

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 }
View Code
原文地址:https://www.cnblogs.com/pegasus923/p/8439650.html