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”. Runtime: 40 ms, faster than 100.00% of C++ online submissions for Find All Anagrams in a String.
    Memory Usage: 7.1 MB, less than 0.89% of C++ online submissions for Find All Anagrams in a String.

    1. class Solution {
    2. public:
    3. vector<int> findAnagrams(string s, string p) {
    4. vector<int> pv(26,0);
    5. vector<int> sv(26,0);
    6. vector<int> result;
    7. if (s.size() < p.size()) {
    8. return result;
    9. }
    10. for(int i = 0; i < p.size(); ++i)
    11. {
    12. ++pv[p[i] - 'a'];
    13. ++sv[s[i] - 'a'];
    14. }
    15. if (pv == sv) {
    16. result.push_back(0);
    17. }
    18. for(int i = p.size(); i < s.size(); ++i)
    19. {
    20. // sv like a stack
    21. ++sv[s[i] - 'a'];
    22. --sv[s[i - p.size()] - 'a'];
    23. if (pv == sv) {
    24. result.push_back(i-p.size() + 1);
    25. }
    26. }
    27. return result;
    28. }
    29. };

    解题思路的流程还是比较清晰的,就是依次对子串跟需要对比的字符串进行异构的判断。
    异构字符串的判断,只需要统计每个字母的数量,如果两个字符串包含的所有字母及个数都相等,则这两个字符串为异构的字符串。

    • 由于被判断字符串 p 是不变的,因此统计的结果可以可缓存的
    • 由于每一次判断子串,都只是首尾下标的变化,因此可以把统计的数组当做栈来使用,可以节省空间和时间复杂度