Open In App

Print all possible combinations of words from Dictionary using Trie

Improve
Improve
Like Article
Like
Save
Share
Report

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.



Last Updated : 09 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads