438-find-all-anagrams-in-a-string

Try it on leetcode

Description

Given two strings s and p, return an array of all the start indices of p's anagrams in s. You may return the answer in any order.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

 

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".

 

Constraints:

  • 1 <= s.length, p.length <= 3 * 104
  • s and p consist of lowercase English letters.

Solution(Python)

class Solution:
    def __init__(self):
        self.a = ord("a")

    def findAnagrams(self, s: str, p: str) -> List[int]:
        return self.windowsliding(s, p)

    """
    create Counter Dict of p
    for all substrings in s:
        check if it's anagram if s 
             
            
    Time Complexty: O(n^2)
    Space Complexity: O(1)
    
    """

    def bruteforce(self, s, p):

        n = len(s)
        cnts = Counter(p)
        res = []
        for i in range(n):
            for j in range(i, n):
                sub_s = s[i: j + 1]
                if Counter(sub_s) == cnts:
                    res.append(i)

        return res

    """
    create Frequency counter table  of p (atmost 26 letters)
    
    create Frequency counter table for current window of size m on s
    
    slide over the s:
        if two frequency table matches:
            add start index to the solution
        increment end of the slider 
        decrement the start of the slider
    
    finally check for substring at the end of the s
            
    Time Complexty: O(n)
    Space Complexity: O(1)          
    """

    def windowsliding(self, s, p):
        n = len(s)
        m = len(p)

        if m > n:
            return []
        res = []

        countP = [0] * 26
        countCW = [0] * 26

        for i in range(m):
            countP[ord(p[i]) - self.a] += 1
            countCW[ord(s[i]) - self.a] += 1

        for i in range(m, n):
            if countP == countCW:
                res.append(i - m)

            countCW[ord(s[i]) - self.a] += 1
            countCW[ord(s[i - m]) - self.a] -= 1

        if countP == countCW:
            res.append(n - m)
        return res