Find All Anagrams in a String [Medium] — Fixed Window + Freq Match

Sanjeev SharmaSanjeev Sharma
2 min read

Advertisement

Problem Statement

Given strings s and p, return all start indices of p's anagrams in s.

Input: s="cbaebabacd", p="abc"Output: [0,6]
Input: s="abab", p="ab"Output: [0,1,2]

Intuition

Fixed window of size len(p). Compare character frequency of window with p's frequency. Track matches counter (number of chars with matching freq).


Solutions

Python

from collections import Counter

def findAnagrams(s: str, p: str) -> list[int]:
    k = len(p)
    if len(s) < k: return []
    need = Counter(p)
    window = Counter(s[:k])
    matches = sum(1 for c in need if window[c] == need[c])
    res = [0] if matches == len(need) else []
    for i in range(k, len(s)):
        # Add right char
        c_in = s[i]; c_out = s[i-k]
        window[c_in] += 1
        if c_in in need:
            if window[c_in] == need[c_in]: matches += 1
            elif window[c_in] == need[c_in]+1: matches -= 1
        # Remove left char
        window[c_out] -= 1
        if c_out in need:
            if window[c_out] == need[c_out]: matches += 1
            elif window[c_out] == need[c_out]-1: matches -= 1
        if window[c_out] == 0: del window[c_out]
        if matches == len(need): res.append(i-k+1)
    return res

C++

vector<int> findAnagrams(string s, string p) {
    if(s.size()<p.size()) return {};
    int freq[26]={}, win[26]={};
    for(char c:p) freq[c-'a']++;
    for(int i=0;i<p.size();i++) win[s[i]-'a']++;
    vector<int> res;
    auto eq=[&](){return equal(freq,freq+26,win);};
    if(eq()) res.push_back(0);
    for(int i=p.size();i<s.size();i++){
        win[s[i]-'a']++; win[s[i-p.size()]-'a']--;
        if(eq()) res.push_back(i-p.size()+1);
    }
    return res;
}

Complexity

  • Time: O(|s|), Space: O(1)

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro