Open In App

Anagram Substring Search (Or Search for all permutations) | Set 2

Improve
Improve
Like Article
Like
Save
Share
Report

Given a text txt[0..n-1] and a pattern pat[0..m-1], write a function search(char pat[], char txt[]) that prints all occurrences of pat[] and its permutations (or anagrams) in txt[]. You may assume that n > m.

Examples:

Input:  txt[] = “BACDGABCDA”  pat[] = “ABCD”
Output:   Found at Index 0
                Found at Index 5
                Found at Index 6

Input: txt[] =  “AAABABAA” pat[] = “AABA”
Output:   Found at Index 0
                Found at Index 1
               Found at Index 4

Approach: The current approach is based on sliding window and hashtable.

  • Create a hashtable to store a hash of all characters in the pattern
  • Create a hashtable to store a hash of all characters in text for window m
  • Traverse the string text in window m and compare the hashtables.
  • If found the same, push the index of substring as one of the answers.

Below is the implementation of the above approach:

C++




// C++ program to search all anagrams
// of a pattern in a text
 
#include <bits/stdc++.h>
#define MAX 256
using namespace std;
 
// Function to find all anagrams using hashtable
vector<int> findAnagrams(string s, string p)
{
    int n = s.length(), m = p.length();
 
    // Vector to store all indices of substrings
    // that are anagram of string p
 
    vector<int> ans;
 
    // Handling edge cases
    if (n < m || m == 0)
        return ans;
 
    // Hashtables for both strings
    vector<int> ms(26, 0), mp(26, 0);
 
    // Initialise the hashtable for string p
    for (char c : p) {
        mp++;
    }
 
    int i = 0;
    bool flag = true;
 
    // Initialise the hashtable
    // for string s for window m
    for (i = 0; i < m; i++) {
        ms[s[i] - 'A']++;
    }
 
    // Check if current hashtables are same
    // for current window m
 
    for (int j = 0; j < 26; j++)
        if (mp[j] != ms[j])
            flag = false;
 
    // if same, push the index of
    // Starting substring into window m
 
    if (flag)
        ans.push_back(0);
 
    // Traverse string s with window m
    for (i = m; i < n; i++) {
        ms[s[i - m] - 'A']--;
        ms[s[i] - 'A']++;
 
        // Check if current hashtables are same
        // for current window m
        if (mp[s[i] - 'A'] == ms[s[i] - 'A']
            && mp[s[i - m] - 'A'] == ms[s[i - m] - 'A']) {
            flag = true;
            for (int j = 0; j < 26; j++)
                if (mp[j] != ms[j])
                    flag = false;
        }
        else
            flag = false;
 
        // if same, push the index
        // of starting substring
        // into answer
        if (flag)
            ans.push_back(i - m + 1);
    }
 
    // Return the final vector of indices
    return ans;
}
 
// Driver program
int main()
{
    char txt[] = "BACDGABCDA";
    char pat[] = "ABCD";
    vector<int> indices = findAnagrams(txt, pat);
    cout << "[ ";
    for (auto i : indices)
        cout << i << " ";
    cout << "]";
    return 0;
}


Java




// Java program to search all anagrams
// of a pattern in a text
import java.util.*;
 
class GFG
{
  static final int MAX = 256;
 
  // Function to find all anagrams using hashtable
  static Vector<Integer> findAnagrams(String s, String p)
  {
    int n = s.length(), m = p.length();
 
    // Vector to store all indices of subStrings
    // that are anagram of String p
 
    Vector<Integer> ans = new Vector<Integer>();
 
    // Handling edge cases
    if (n < m || m == 0)
      return ans;
 
    // Hashtables for both Strings
    int [] ms = new int[26];
    int [] mp = new int[26];
 
    // Initialise the hashtable for String p
    for (char c : p.toCharArray()) {
      mp++;
    }
 
    int i = 0;
    boolean flag = true;
 
    // Initialise the hashtable
    // for String s for window m
    for (i = 0; i < m; i++) {
      ms[s.charAt(i) - 'A']++;
    }
 
    // Check if current hashtables are same
    // for current window m
 
    for (int j = 0; j < 26; j++)
      if (mp[j] != ms[j])
        flag = false;
 
    // if same, push the index of
    // Starting subString into window m
 
    if (flag)
      ans.add(0);
 
    // Traverse String s with window m
    for (i = m; i < n; i++) {
      ms[s.charAt(i-m) - 'A']--;
      ms[s.charAt(i) - 'A']++;
 
      // Check if current hashtables are same
      // for current window m
      if (mp[s.charAt(i) - 'A'] == ms[s.charAt(i) - 'A']
          && mp[s.charAt(i-m) - 'A'] == ms[s.charAt(i-m) - 'A']) {
        flag = true;
        for (int j = 0; j < 26; j++)
          if (mp[j] != ms[j])
            flag = false;
      }
      else
        flag = false;
 
      // if same, push the index
      // of starting subString
      // into answer
      if (flag)
        ans.add(i - m + 1);
    }
 
    // Return the final vector of indices
    return ans;
  }
 
  // Driver program
  public static void main(String[] args)
  {
    String txt = "BACDGABCDA";
    String pat = "ABCD";
    Vector<Integer> indices = findAnagrams(txt, pat);
    System.out.print("[ ");
    for (int i : indices)
      System.out.print(i+ " ");
    System.out.print("]");
  }
}
 
// This code is contributed by shikhasingrajput


Python3




# python3 program to search all anagrams
# of a pattern in a text
MAX = 256
 
# Function to find all anagrams using hashtable
def findAnagrams(s, p):
 
    n, m = len(s), len(p)
 
    # Vector to store all indices of substrings
    # that are anagram of string p
 
    ans = []
 
    # Handling edge cases
    if (n < m or m == 0):
        return ans
 
    # Hashtables for both strings
    ms, mp = [0 for _ in range(26)], [0 for _ in range(26)]
 
    # Initialise the hashtable for string p
    for c in p:
        mp[ord(c) - ord('A')] += 1
 
    i = 0
    flag = True
 
    # Initialise the hashtable
    # for string s for window m
    for i in range(0, m):
        ms[ord(s[i]) - ord('A')] += 1
 
    # Check if current hashtables are same
    # for current window m
 
    for j in range(0, 26):
        if (mp[j] != ms[j]):
            flag = False
 
    # if same, push the index of
    # Starting substring into window m
 
    if (flag):
        ans.append(0)
 
    # Traverse string s with window m
    for i in range(m, n):
        ms[ord(s[i - m]) - ord('A')] -= 1
        ms[ord(s[i]) - ord('A')] += 1
 
        # Check if current hashtables are same
        # for current window m
        if (mp[ord(s[i]) - ord('A')] == ms[ord(s[i]) - ord('A')]
                and mp[ord(s[i - m]) - ord('A')] == ms[ord(s[i - m]) - ord('A')]):
            flag = True
            for j in range(0, 26):
                if (mp[j] != ms[j]):
                    flag = False
 
        else:
            flag = False
 
        # if same, push the index
        # of starting substring
        # into answer
        if (flag):
            ans.append(i - m + 1)
 
    # Return the final vector of indices
    return ans
 
# Driver program
if __name__ == "__main__":
 
    txt = "BACDGABCDA"
    pat = "ABCD"
    indices = findAnagrams(txt, pat)
    print("[ ", end="")
    for i in indices:
        print(i, end=" ")
    print("]")
 
# This code is contributed by rakeshsahni


C#




// C# program to search all anagrams
// of a pattern in a text
using System;
using System.Collections;
 
class GFG {
 
    static int MAX = 256;
 
    // Function to find all anagrams using hashtable
    static ArrayList findAnagrams(string s, string p)
    {
        int n = s.Length, m = p.Length;
 
        // Vector to store all indices of subStrings
        // that are anagram of String p
 
        ArrayList ans = new ArrayList();
 
        // Handling edge cases
        if (n < m || m == 0)
            return ans;
 
        // Hashtables for both Strings
        int[] ms = new int[26];
        int[] mp = new int[26];
 
        // Initialise the hashtable for String p
        foreach(char c in p.ToCharArray())
        {
            mp++;
        }
 
        int i = 0;
        bool flag = true;
 
        // Initialise the hashtable
        // for String s for window m
        for (i = 0; i < m; i++) {
            ms[s[i] - 'A']++;
        }
 
        // Check if current hashtables are same
        // for current window m
 
        for (int j = 0; j < 26; j++)
            if (mp[j] != ms[j])
                flag = false;
 
        // if same, push the index of
        // Starting subString into window m
 
        if (flag)
            ans.Add(0);
 
        // Traverse String s with window m
        for (i = m; i < n; i++) {
            ms[s[i - m] - 'A']--;
            ms[s[i] - 'A']++;
 
            // Check if current hashtables are same
            // for current window m
            if (mp[s[i] - 'A'] == ms[s[i] - 'A']
                && mp[s[i - m] - 'A']
                       == ms[s[i - m] - 'A']) {
                flag = true;
                for (int j = 0; j < 26; j++)
                    if (mp[j] != ms[j])
                        flag = false;
            }
            else
                flag = false;
 
            // if same, push the index
            // of starting subString
            // into answer
            if (flag)
                ans.Add(i - m + 1);
        }
 
        // Return the final vector of indices
        return ans;
    }
 
    // Driver program
    public static void Main()
    {
        string txt = "BACDGABCDA";
        string pat = "ABCD";
        ArrayList indices = findAnagrams(txt, pat);
        Console.Write("[ ");
        foreach(int i in indices) Console.Write(i + " ");
        Console.Write("]");
    }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript




<script>
       // JavaScript code for the above approach
       let MAX = 256
 
       // Function to find all anagrams using hashtable
       function findAnagrams(s, p)
       {
           let n = s.length, m = p.length;
 
           // Vector to store all indices of substrings
           // that are anagram of string p
           let ans = [];
 
           // Handling edge cases
           if (n < m || m == 0)
               return ans;
 
           // Hashtables for both strings
           let ms = new Array(26).fill(0), mp = new Array(26).fill(0);
 
           // Initialise the hashtable for string p
           for (let i = 0; i < p.length; i++) {
               mp[p[i].charCodeAt(0) - 'A'.charCodeAt(0)]++;
           }
 
           let i = 0;
           let flag = true;
 
           // Initialise the hashtable
           // for string s for window m
           for (i = 0; i < m; i++) {
               ms[s[i].charCodeAt(0) - 'A'.charCodeAt(0)]++;
           }
 
           // Check if current hashtables are same
           // for current window m
 
           for (let j = 0; j < 26; j++)
               if (mp[j] != ms[j])
                   flag = false;
 
           // if same, push the index of
           // Starting substring into window m
 
           if (flag)
               ans.push(0);
 
           // Traverse string s with window m
           for (i = m; i < n; i++) {
               ms[s[i - m].charCodeAt(0) - 'A'.charCodeAt(0)]--;
               ms[s[i].charCodeAt(0) - 'A'.charCodeAt(0)]++;
 
               // Check if current hashtables are same
               // for current window m
               if (mp[s[i].charCodeAt(0) - 'A'.charCodeAt(0)] == ms[s[i].charCodeAt(0) - 'A'.charCodeAt(0)]
                   && mp[s[i - m].charCodeAt(0) - 'A'.charCodeAt(0)] == ms[s[i - m].charCodeAt(0) - 'A'.charCodeAt(0)]) {
                   flag = true;
                   for (let j = 0; j < 26; j++)
                       if (mp[j] != ms[j])
                           flag = false;
               }
               else
                   flag = false;
 
               // if same, push the index
               // of starting substring
               // into answer
               if (flag)
                   ans.push(i - m + 1);
           }
 
           // Return the final vector of indices
           return ans;
       }
 
       // Driver program
 
       let txt = "BACDGABCDA";
       let pat = "ABCD";
       let indices = findAnagrams(txt, pat);
       document.write("[ ");
       for (let i of indices)
           document.write(i + " ");
       document.write("]");
 
      // This code is contributed by Potta Lokesh
   </script>


Output

[ 0 5 6 ]

Time complexity:  O(N)
Auxiliary Space: O(1)



Last Updated : 10 Mar, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads