Python | Get the smallest window in a string containing all characters of given pattern

Given two strings str and pattern, find the smallest substring in str containing all characters of pattern efficiently.

Examples:

Input : str = 'geeksforgeeks' pattern = 'gks' 
Output : geeks

Input : str = 'new string' pattern = 'rg' 
Output : ring

Approach #1 : Using Python enumerate()
This method uses Python enumerate(). need[k] store how many times we need character k and missing tells how many characters are still missing. In the loop, first add the new character to the window. Then, if nothing is missing, remove as much as possible from the window start and then update the result.

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 code to Find the smallest 
# window in a string containing all 
# characters of another string
from collections import Counter
  
# Function to find smallest window containing 
# all characters of 'pat' 
def min_window(str, pattern):
      
    # To store no. of missing characters
    missing = len(pattern)
      
    # To count no. of characters needed
    need = Counter(pattern)
    I = J = i = 0
      
    # Traversing through enumerate
    for j, k in enumerate(str, 1):
        missing -= need[k] > 0
        need[k] -= 1
          
        # If nothing is missing, remove as much as 
        # possible from the window start 
        if not missing:
            while need[str[i]] < 0:
                need[str[i]] += 1; i += 1
                  
            if not J or j - i <= J - I:
                I, J = i, j
                  
            need[str[i]] += 1; i += 1
            missing += 1
              
    # Returning result window        
    return str[I : J]
  
# Driver Code
string = "geeksforgeeks"
pattern = "fks"
print(min_window(string, pattern))

chevron_right


Output:

ksf

 
Approach #2 : Using collections.defaultdict()
This method make use of two defaultdicts ‘src’ and ‘dest’. A defaultdict works exactly like a normal dict, but it is initialized with a function (“default factory”) that takes no arguments. source is empty while target consist of pattern elements as keys and the count of occurrence as value. In every iteration ‘i’, we check if the ith element of str is present in target dictionary or not and update source dictionary accordingly.

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 code to Find the smallest 
# window in a string containing all 
# characters of another string
from collections import defaultdict
import sys
def min_window(str, pattern):
          
        # Function to check validity of source and 
        # destination
        def isValid(i, j):
            for item in j:
                if item not in i or i[item] < j[item]:
                    return False
            return True
          
        source = defaultdict(int)
        target = defaultdict(int)
          
        # Target consist pattern elements and 1 
        # as key:value pair
        for e in pattern:
            target[e] += 1
          
        # Minimum length for window    
        minLen = sys.maxsize
        n = len(str)
        ans, j = '', 0 
        for i in range(n):
              
            # Update source for valid source - target pair
            while j < n and (isValid(source, target) == False):
                source[str[j]] += 1
                j += 1
              
            # Checking validity of source-target pair
            if isValid(source, target):
                if minLen > j-i + 1:
                    minLen = j-i + 1
                    ans = str[i:j]
            source[str[i]] -= 1
        return ans
  
# Driver Code
string = "geekforgeeks"
pattern = "gks"
print(min_window(string, pattern))

chevron_right


Output:

geeks

 
Approach #3 : Dynamic approach
In this method, we use a for loop and in every iteration, say i, we find the shortest interval that ends in i and includes all letters in the pattern. This can be done by taking two data structures in account i.e. ‘rpos’ and ‘rdict’. rpos is a sorted list of positions where rightmost positions of characters of pattern in str are kept and rdict is a dictionary mapping from a character to the position. values of rdict is same as rpos.

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 code to Find the smallest 
# window in a string containing all 
# characters of another string
from collections import Counter, defaultdict
  
def min_window(str, pattern):
      
    rdict, count = defaultdict(list), Counter(pattern)
    rpos, res = [], "" 
      
    # Loop only over c exist in pattern
    for i, c in filter(lambda x: x[1] in pattern, enumerate(str)): 
        if len(rdict) == count: 
            # If reached limit, remove
            rpos.remove(rdict.pop(0))
              
        # Add to dict
        rdict[i].append(i)
        # Add to list
        rpos.append(i) 
          
        if (len(rpos) == len(pattern) and
           (res =="" or rpos[-1]-rpos[0]<len(res))):
            res = str[rpos[0]:rpos[-1]+1
              
    return res
  
# Driver Code
string = "geeksforgeeks"
pattern = "gks"
print(min_window(string, pattern))

chevron_right


Output:

geeks


My Personal Notes arrow_drop_up


If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.