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.