Program to find start indices of all anagrams of a string S in T in Python

Suppose we have two strings S and T, we have to find all the start indices of S's anagrams in T. The strings consist of lowercase letters only and the length of both strings S and T will not be larger than 20 and 100.

So, if the input is like S = "cab" T = "bcabxabc", then the output will be [0, 1, 5] as the substrings "bca", "cab" and "abc" are anagrams of "cab".

Using Sliding Window with Character Count

We can solve this using a sliding window approach with character frequency counting ?

def find_anagrams(s, p):
    from collections import Counter
    
    if len(p) > len(s):
        return []
    
    p_count = Counter(p)
    window_count = Counter()
    result = []
    
    # Initialize the window
    for i in range(len(p)):
        window_count[s[i]] += 1
    
    # Check if first window is anagram
    if window_count == p_count:
        result.append(0)
    
    # Slide the window
    for i in range(len(p), len(s)):
        # Add new character
        window_count[s[i]] += 1
        
        # Remove old character
        left_char = s[i - len(p)]
        window_count[left_char] -= 1
        if window_count[left_char] == 0:
            del window_count[left_char]
        
        # Check if current window is anagram
        if window_count == p_count:
            result.append(i - len(p) + 1)
    
    return result

# Test the function
s = "bcabxabc"
p = "cab"
print(find_anagrams(s, p))
[0, 1, 5]

Using Dictionary-based Approach

Here's another approach using dictionary to track character frequencies ?

def find_anagrams_dict(s, p):
    if len(p) > len(s):
        return []
    
    # Count characters in pattern
    p_dict = {}
    for char in p:
        p_dict[char] = p_dict.get(char, 0) + 1
    
    result = []
    window_size = len(p)
    
    # Check each window of size len(p)
    for i in range(len(s) - len(p) + 1):
        window = s[i:i + window_size]
        
        # Count characters in current window
        window_dict = {}
        for char in window:
            window_dict[char] = window_dict.get(char, 0) + 1
        
        # Compare dictionaries
        if window_dict == p_dict:
            result.append(i)
    
    return result

# Test the function
s = "bcabxabc"
p = "cab"
print(find_anagrams_dict(s, p))
[0, 1, 5]

Optimized Sliding Window

This optimized version maintains a match counter to avoid comparing entire dictionaries ?

def find_anagrams_optimized(s, p):
    if len(p) > len(s):
        return []
    
    # Character frequency map for pattern
    p_count = {}
    for char in p:
        p_count[char] = p_count.get(char, 0) + 1
    
    result = []
    left = 0
    matches = 0
    window_count = {}
    
    for right in range(len(s)):
        # Add character from right
        right_char = s[right]
        if right_char not in window_count:
            window_count[right_char] = 0
        window_count[right_char] += 1
        
        if right_char in p_count and window_count[right_char] == p_count[right_char]:
            matches += 1
        
        # Remove character from left if window is too large
        if right >= len(p):
            left_char = s[left]
            if left_char in p_count and window_count[left_char] == p_count[left_char]:
                matches -= 1
            window_count[left_char] -= 1
            left += 1
        
        # Check if we found an anagram
        if matches == len(p_count):
            result.append(left)
    
    return result

# Test the function
s = "bcabxabc"
p = "cab"
print(find_anagrams_optimized(s, p))
[0, 1, 5]

Comparison

Method Time Complexity Space Complexity Best For
Counter Approach O(n) O(k) Clean, readable code
Dictionary Approach O(n * k) O(k) Simple implementation
Optimized Sliding Window O(n) O(k) Maximum efficiency

Where n is the length of string s and k is the length of pattern p.

Conclusion

The sliding window approach with Counter provides the best balance of efficiency and readability. Use the optimized version when performance is critical, and the dictionary approach for educational purposes to understand the core logic.

Updated on: 2026-03-25T11:56:21+05:30

368 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements