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 6Input: 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> |
[ 0 5 6 ]
Time complexity: O(N)
Auxiliary Space: O(1)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!