Print all possible combinations of words from Dictionary using Trie
Given an array of strings arr[], for every string in the array, print all possible combinations of strings that can be concatenated to make that word. Examples:
Input: arr[] = ["sam", "sung", "samsung"] Output: sam: sam sung: sung samsung: sam sung samsung String 'samsung' can be formed using two different strings from the array i.e. 'sam' and 'sung' whereas 'samsung' itself is also a string in the array. Input: arr[] = ["ice", "cream", "icecream"] Output: ice: ice cream: cream icecream: ice cream icecream
Approach:
- Add all the given strings into trie.
- Process every prefix character by character and check if it forms a word from trie by searching.
- If the prefix is present in the trie then add it to the result and proceed further with the remaining suffix in the string.
- Once it reaches the end of the string, print all the combinations found.
Below is the implementation of the above approach:
CPP
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; const int ALPHABET_SIZE = 26; // Trie node struct TrieNode { struct TrieNode* children[ALPHABET_SIZE]; // isEndOfWord is true if node // represents the end of the word bool isEndOfWord; }; // Returns new trie node struct TrieNode* getNode( void ) { struct TrieNode* pNode = new TrieNode; pNode->isEndOfWord = false ; for ( int i = 0; i < ALPHABET_SIZE; i++) pNode->children[i] = NULL; return pNode; } // If not present, inserts key into trie // If the key is prefix of trie node, // marks the node as leaf node void insert( struct TrieNode* root, string key) { struct TrieNode* pCrawl = root; for ( int i = 0; i < key.length(); i++) { int index = key[i] - 'a' ; if (!pCrawl->children[index]) pCrawl->children[index] = getNode(); pCrawl = pCrawl->children[index]; } // Mark node as leaf pCrawl->isEndOfWord = true ; } // Returns true if the key is present in the trie bool search( struct TrieNode* root, string key) { struct TrieNode* pCrawl = root; for ( int i = 0; i < key.length(); i++) { int index = key[i] - 'a' ; if (!pCrawl->children[index]) return false ; pCrawl = pCrawl->children[index]; } return (pCrawl != NULL && pCrawl->isEndOfWord); } // Result stores the current prefix with // spaces between words void wordBreakAll(TrieNode* root, string word, int n, string result) { // Process all prefixes one by one for ( int i = 1; i <= n; i++) { // Extract substring from 0 to i in prefix string prefix = word.substr(0, i); // If trie contains this prefix then check // for the remaining string. // Otherwise ignore this prefix if (search(root, prefix)) { // If no more elements are there then print if (i == n) { // Add this element to the previous prefix result += prefix; // If(result == word) then return // If you don't want to print last word cout << "\t" << result << endl; return ; } wordBreakAll(root, word.substr(i, n - i), n - i, result + prefix + " " ); } } } // Driver code int main() { struct TrieNode* root = getNode(); string dictionary[] = { "sam" , "sung" , "samsung" }; int n = sizeof (dictionary) / sizeof (string); for ( int i = 0; i < n; i++) { insert(root, dictionary[i]); } for ( int i = 0; i < n; i++) { cout << dictionary[i] << ": \n" ; wordBreakAll(root, dictionary[i], dictionary[i].length(), "" ); } return 0; } |
Java
// Java implementation of the approach import java.io.*; public class GFG { static int ALPHABET_SIZE = 26 ; // Trie node static class TrieNode { TrieNode []children = new TrieNode[ALPHABET_SIZE]; // isEndOfWord is true if node // represents the end of the word boolean isEndOfWord; public TrieNode() { super (); } }; // Returns new trie node static TrieNode getNode() { TrieNode pNode = new TrieNode(); pNode.isEndOfWord = false ; for ( int i = 0 ; i < ALPHABET_SIZE; i++) pNode.children[i] = null ; return pNode; } // If not present, inserts key into trie // If the key is prefix of trie node, // marks the node as leaf node static void insert(TrieNode root, String key) { TrieNode pCrawl = root; for ( int i = 0 ; i < key.length(); i++) { int index = key.charAt(i) - 'a' ; if (pCrawl.children[index] == null ) pCrawl.children[index] = getNode(); pCrawl = pCrawl.children[index]; } // Mark node as leaf pCrawl.isEndOfWord = true ; } // Returns true if the key is present in the trie static boolean search(TrieNode root, String key) { TrieNode pCrawl = root; for ( int i = 0 ; i < key.length(); i++) { int index = key.charAt(i) - 'a' ; if (pCrawl.children[index] == null ) return false ; pCrawl = pCrawl.children[index]; } return (pCrawl != null && pCrawl.isEndOfWord); } // Result stores the current prefix with // spaces between words static void wordBreakAll(TrieNode root, String word, int n, String result) { // Process all prefixes one by one for ( int i = 1 ; i <= n; i++) { // Extract subString from 0 to i in prefix String prefix = word.substring( 0 , i); // If trie contains this prefix then check // for the remaining String. // Otherwise ignore this prefix if (search(root, prefix)) { // If no more elements are there then print if (i == n) { // Add this element to the previous prefix result += prefix; // If(result == word) then return // If you don't want to print last word System.out.print( "\t" + result + "\n" ); return ; } wordBreakAll(root, word.substring(i, n), n - i, result + prefix + " " ); } } } // Driver code public static void main(String[] args) { new TrieNode(); TrieNode root = getNode(); String dictionary[] = { "sam" , "sung" , "samsung" }; int n = dictionary.length; for ( int i = 0 ; i < n; i++) { insert(root, dictionary[i]); } for ( int i = 0 ; i < n; i++) { System.out.print(dictionary[i]+ ": \n" ); wordBreakAll(root, dictionary[i], dictionary[i].length(), "" ); } } } // This code is contributed by PrinciRaj1992 |
Python3
# Python3 implementation of the approach class GFG : # Trie node class TrieNode : children = [ None ] * 26 # isEndOfWord is true if node # represents the end of the word isEndOfWord = False # Returns new trie node @staticmethod def getNode() : pNode = GFG.TrieNode() pNode.isEndOfWord = False i = 0 while (i < 26 ) : pNode.children[i] = None i + = 1 return pNode # If not present, inserts key into trie # If the key is prefix of trie node, # marks the node as leaf node @staticmethod def insert( root, key) : pCrawl = root i = 0 while (i < len (key)) : index = ord (key[i]) - ord ( 'a' ) if (pCrawl.children[index] = = None ) : pCrawl.children[index] = GFG.getNode() pCrawl = pCrawl.children[index] i + = 1 # Mark node as leaf pCrawl.isEndOfWord = True # Returns true if the key is present in the trie @staticmethod def search( root, key) : pCrawl = root i = 0 while (i < len (key)) : index = ord (key[i]) - ord ( 'a' ) if (pCrawl.children[index] = = None ) : return False pCrawl = pCrawl.children[index] i + = 1 return (pCrawl ! = None and pCrawl.isEndOfWord) # Result stores the current prefix with # spaces between words @staticmethod def wordBreakAll( root, word, n, result) : # Process all prefixes one by one i = 1 while (i < = n) : # Extract subString from 0 to i in prefix prefix = word[ 0 :i] # If trie contains this prefix then check # for the remaining String. # Otherwise ignore this prefix if (GFG.search(root, prefix)) : # If no more elements are there then print if (i = = n) : # Add this element to the previous prefix result + = prefix # If(result == word) then return # If you don't want to print last word print ( "\t" + result + "\n" , end = "") return GFG.wordBreakAll(root, word[i:n], n - i, result + prefix + " " ) i + = 1 # Driver code @staticmethod def main( args) : GFG.TrieNode() root = GFG.getNode() dictionary = [ "sam" , "sung" , "samsung" ] n = len (dictionary) i = 0 while (i < n) : GFG.insert(root, dictionary[i]) i + = 1 i = 0 while (i < n) : print (dictionary[i] + ": \n" , end = "") GFG.wordBreakAll(root, dictionary[i], len (dictionary[i]), "") i + = 1 if __name__ = = "__main__" : GFG.main([]) # This code is contributed by aadityaburujwale. |
C#
// C# implementation of the approach using System; class GFG { static int ALPHABET_SIZE = 26; // Trie node class TrieNode { public TrieNode []children = new TrieNode[ALPHABET_SIZE]; // isEndOfWord is true if node // represents the end of the word public bool isEndOfWord; public TrieNode() { } }; // Returns new trie node static TrieNode getNode() { TrieNode pNode = new TrieNode(); pNode.isEndOfWord = false ; for ( int i = 0; i < ALPHABET_SIZE; i++) pNode.children[i] = null ; return pNode; } // If not present, inserts key into trie // If the key is prefix of trie node, // marks the node as leaf node static void insert(TrieNode root, String key) { TrieNode pCrawl = root; for ( int i = 0; i < key.Length; i++) { int index = key[i] - 'a' ; if (pCrawl.children[index] == null ) pCrawl.children[index] = getNode(); pCrawl = pCrawl.children[index]; } // Mark node as leaf pCrawl.isEndOfWord = true ; } // Returns true if the key is present in the trie static bool search(TrieNode root, String key) { TrieNode pCrawl = root; for ( int i = 0; i < key.Length; i++) { int index = key[i] - 'a' ; if (pCrawl.children[index] == null ) return false ; pCrawl = pCrawl.children[index]; } return (pCrawl != null && pCrawl.isEndOfWord); } // Result stores the current prefix with // spaces between words static void wordBreakAll(TrieNode root, String word, int n, String result) { // Process all prefixes one by one for ( int i = 1; i <= n; i++) { // Extract subString from 0 to i in prefix String prefix = word.Substring(0, i); // If trie contains this prefix then check // for the remaining String. // Otherwise ignore this prefix if (search(root, prefix)) { // If no more elements are there then print if (i == n) { // Add this element to the previous prefix result += prefix; // If(result == word) then return // If you don't want to print last word Console.Write( "\t" + result + "\n" ); return ; } wordBreakAll(root, word.Substring(i, n - i), n - i, result + prefix + " " ); } } } // Driver code public static void Main(String[] args) { new TrieNode(); TrieNode root = getNode(); String []dictionary = { "sam" , "sung" , "samsung" }; int n = dictionary.Length; for ( int i = 0; i < n; i++) { insert(root, dictionary[i]); } for ( int i = 0; i < n; i++) { Console.Write(dictionary[i]+ ": \n" ); wordBreakAll(root, dictionary[i], dictionary[i].Length, "" ); } } } // This code is contributed by PrinciRaj1992 |
Javascript
// JavaScript implementation of the approach const ALPHABET_SIZE = 26; // Trie node class TrieNode { constructor() { this .children = new Array(ALPHABET_SIZE); // isEndOfWord is true if node // represents the end of the word this .isEndOfWord = false ; } } // Returns new trie node const getNode = () => { let pNode = new TrieNode(); pNode.isEndOfWord = false ; for (let i = 0; i < ALPHABET_SIZE; i++) { pNode.children[i] = null ; } return pNode; }; // If not present, inserts key into trie // If the key is prefix of trie node, // marks the node as leaf node const insert = (root, key) => { let pCrawl = root; for (let i = 0; i < key.length; i++) { let index = key.charCodeAt(i) - 97; if (pCrawl.children[index] == null ) { pCrawl.children[index] = getNode(); } pCrawl = pCrawl.children[index]; } // Mark node as leaf pCrawl.isEndOfWord = true ; }; // Returns true if the key is present in the trie const search = (root, key) => { let pCrawl = root; for (let i = 0; i < key.length; i++) { let index = key.charCodeAt(i) - 97; if (pCrawl.children[index] == null ) return false ; pCrawl = pCrawl.children[index]; } return (pCrawl != null && pCrawl.isEndOfWord); }; // Result stores the current prefix with // spaces between words const wordBreakAll = (root, word, n, result) => { // Process all prefixes one by one for (let i = 1; i <= n; i++) { // Extract subString from 0 to i in prefix let prefix = word.substring(0, i); // If trie contains this prefix then check // for the remaining String. // Otherwise ignore this prefix if (search(root, prefix)) { // If no more elements are there then print if (i == n) { // Add this element to the previous prefix result += prefix; // If(result == word) then return // If you don't want to print last word console.log(`\t${result}`); return ; } wordBreakAll(root, word.substring(i, n), n - i, result + prefix + " " ); } } }; // Driver code const main = () => { let root = getNode(); let dictionary = [ "sam" , "sung" , "samsung" ]; let n = dictionary.length; for (let i = 0; i < n; i++) { insert(root, dictionary[i]); } for (let i = 0; i < n; i++) { console.log(`${dictionary[i]}:`); wordBreakAll(root, dictionary[i], dictionary[i].length, "" ); } } main(); // This code is contributed by akashish__ |
Output:
sam: sam sung: sung samsung: sam sung samsung
Time Complexity: O(n*s2) where n is the number of words and s is the maximum length of the word in the list of words.
Auxiliary Space: O(m*ALPHABET_SIZE) m is the total number of characters in all the words stored in the trie.
Please Login to comment...