Given a sequence of words, print all anagrams together


Anagrams − An anagram is a word or a phrase formed by rearranging the alphabets of another word or phrase, usually once. Some examples of anagrams are given below −

  • Top - Pot

  • Silent - Listen

  • Post - Stop

  • Dog - God

Problem Statement

Given an array of words arr[]. For the given array print all the anagrams together.

Sample Example 1

Input

arr[] = {“star”, “god”, “vile”, “save”, “evil”, “care”, “arts”, “race”, “dog”, “vase”}

Output

arts star 
care race 
dog god 
evil vile 
save vase

Explanation

Anagrams in the given array are −

star - arts
god - dog
vile - evil
save - vase
care - race

Sample Example 2

Input

arr[] = {“thing”, “top”, “inlets”, “pot”, “opt”, “listen”, “night”}

Output

inlets listen 
night thing 
opt pot top 

Explanation

Anagrams in the given array are −

thing - night
top - pot - opt
inlets - listen

Approach 1: Word Sorting

An approach to solve the problem is to sort the words in the arr[] and create a map where the key is the sorted word and values are the indices of the words having the same word after sorting. Print anagrams according to the indices stored in the original array.

Pseudocode

function anagrams(arr: vector of strings) -> set of sets of strings
   initialize an empty set of sets called 'res'    
   create a copy of 'arr' called 'list'    
   for each word 's' in 'list'
      sort the characters of 's' in ascending order
      initialize an empty unordered map called 'map' (key: string, value: vector of integers)    
   for i = 0 to size of 'arr' - 1
      add the index 'i' to the vector associated with the sorted word 'list[i]' in 'map'    
   for each entry in 'map'
      initialize an empty set of strings called 'temp'        
      for each index 'i' in entry's value vector
         add 'arr[i]' to 'temp'        
      if size of 'temp' > 1
         add 'temp' to 'res'
      return 'res'

Example: C++ Implementation

The following program prints all the anagrams together.

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <set>
#include <algorithm>
using namespace std;

// Function to group anangrams together from the input array
set<set<string>> anagrams(vector<string> const &arr){
   set<set<string>> res;
   vector<string> list(arr);
   // Sorting words
   for (string &s : list){
      sort(s.begin(), s.end());
   }
   // Pushing sorted words into map along with indices
   unordered_map<string, vector<int>> map;
   for (int i = 0; i < arr.size(); i++){
      map[list[i]].push_back(i);
   }
   for (auto itr : map){
      set<string> temp;
      for (int i : itr.second){
         temp.insert(arr[i]);
      }
      if (temp.size() > 1){
         res.insert(temp);
      }
   }
   return res;
}
int main(){
   vector<string> arr = {"thing", "top", "inlets", "pot", "opt", "listen", "night"};
   set<set<string>> res = anagrams(arr);
   for (set<string> r : res){
      for (string s : r){
         cout << s << ' ';
      }
      cout << endl;
   }
   return 0;
}

Output

inlets listen 
night thing 
opt pot top

Time Complexity − O(N*K logK) where N is the size of the input array and K is the average length of strings.

Space Complexity − O(N)

Approach 2: Using Multimap

For efficient grouping in the above code, we’ll use multimap. Maultimap offers efficient grouping, constant time insertion, fast lookup, collision handling and dynamic size.

Pseudocode

function anagrams(arr: vector of strings) -> set of sets of strings
   res = empty set of sets of strings
    
   list = copy of arr
   for each s in list
      sort the characters of s in ascending order
    
   map = empty unordered multimap of string to integer
   for i = 0 to size of arr - 1
      insert the pair (list[i], i) into map
    
   itr = iterator pointing to the beginning of map
   while itr is not at the end of map
      temp = empty set of strings
        
      curr = copy of itr
      while itr is not at the end of map and itr's key is the same as curr's key
         add arr[itr's value] to temp
         move itr to the next element
        
      if size of temp > 1
         add temp to res
    
   return res

Example: C++ Implementation

The following program prints all the anagrams together.

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <set>
#include <algorithm>
using namespace std;

// Function to group anangrams together from the input array
set<set<string>> anagrams(vector<string> const &arr){
   set<set<string>> res;
   vector<string> list(arr);
   // Sorting words
   for (string &s : list){
      sort(s.begin(), s.end());
   }
   unordered_multimap<string, int> map;
   for (int i = 0; i < arr.size(); i++){
      map.insert(make_pair(list[i], i));
   }
   auto itr = map.begin();
   while (itr != map.end()){
      set<string> temp;
      for (auto curr = itr; itr != map.end() && itr->first == curr->first; itr++){
         temp.insert(arr[itr->second]);
      }
      if (temp.size() > 1){
         res.insert(temp);
      }
   }
   return res;
}
int main(){
   vector<string> arr = {"thing", "top", "inlets", "pot", "opt", "listen", "night"};
   set<set<string>> res = anagrams(arr);
   for (set<string> r : res){
      for (string s : r){
         cout << s << ' ';
      }
      cout << endl;
   }
   return 0;
}

Output

inlets listen 
night thing 
opt pot top

Time Complexity − O(N*K logK + N + N*M) where N is the size of the input array and K is the average length of strings.

Space Complexity − O(N)

Conclusion

In conclusion, the provided C++ code efficiently groups anagrams from a given list of words based on their sorted representations. The solution provided are efficient and can be easily molded depending on particular use cases.

Updated on: 03-Nov-2023

171 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements