Open In App
Related Articles

Print all possible combinations of words from Dictionary using Trie

Improve Article
Improve
Save Article
Save
Like Article
Like

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.


Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!

Last Updated : 09 Feb, 2023
Like Article
Save Article
Previous
Next
Similar Reads
Complete Tutorials