Word Break Problem | (Trie solution) - GeeksforGeeks

10 Aug, 2020
Given an input string and a dictionary of words, find out if the input string can be segmented into a space-separated sequence of dictionary words. See following examples for more details. This is a famous Google interview question, also being asked by many other companies now a days. 
Consider the following dictionary 
{ i, like, sam, sung, samsung, mobile, ice, 
  cream, icecream, man, go, mango}

Input:  ilike
Output: Yes 
The string can be segmented as "i like".

Input:  ilikesamsung
Output: Yes
The string can be segmented as "i like samsung" or 
"i like sam sung".



 
The solution discussed here is mainly an extension of below DP based solution. Dynamic Programming | Set 32 (Word Break Problem)
In the above post, a simple array is used to store and search words in a dictionary. Here we use Trie to do these tasks quickly.
C++
Java
Python3
// A DP and Trie based program to test whether// a given string can be segmented into// space separated words in dictionary#include <iostream>using namespace std;  const int ALPHABET_SIZE = 26;  // trie nodestruct TrieNode{    struct TrieNode *children[ALPHABET_SIZE];      // isEndOfWord is true if the node represents    // end of a word    bool isEndOfWord;};  // Returns new trie node (initialized to NULLs)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, just// marks leaf nodevoid 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 last node as leaf    pCrawl->isEndOfWord = true;}  // Returns true if key presents in trie, else// falsebool 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);}  // returns true if string can be segmented into// space separated words, otherwise returns falsebool wordBreak(string str, TrieNode *root){    int size = str.size();      // Base case    if (size == 0)  return true;      // Try all prefixes of lengths from 1 to size    for (int i=1; i<=size; i++)    {        // The parameter for search is str.substr(0, i)        // str.substr(0, i) which is prefix (of input        // string) of length 'i'. We first check whether        // current prefix is in dictionary. Then we        // recursively check for remaining string        // str.substr(i, size-i) which is suffix of        // length size-i        if (search(root, str.substr(0, i)) &&            wordBreak(str.substr(i, size-i), root))            return true;    }      // If we have tried all prefixes and none    // of them worked    return false;}  // Driver program to test above functionsint main(){    string dictionary[] = {"mobile","samsung","sam",                           "sung","ma\n","mango",                           "icecream","and","go","i",                           "like","ice","cream"};    int n = sizeof(dictionary)/sizeof(dictionary[0]);    struct TrieNode *root = getNode();      // Construct trie    for (int i = 0; i < n; i++)        insert(root, dictionary[i]);      wordBreak("ilikesamsung", root)? cout <<"Yes\n": cout << "No\n";    wordBreak("iiiiiiii", root)? cout <<"Yes\n": cout << "No\n";    wordBreak("", root)? cout <<"Yes\n": cout << "No\n";    wordBreak("ilikelikeimangoiii", root)? cout <<"Yes\n": cout << "No\n";    wordBreak("samsungandmango", root)? cout <<"Yes\n": cout << "No\n";    wordBreak("samsungandmangok", root)? cout <<"Yes\n": cout << "No\n";    return 0;}
// A DP and Trie based program to test whether// a given string can be segmented into// space separated words in dictionaryimport java.util.*;import java.io.*;  class GFG{  static final int ALPHABET_SIZE = 26;  // trie nodestatic class TrieNode{    TrieNode children[];      // isEndOfWord is true if the node    // represents end of a word    boolean isEndOfWord;      // Constructor of TrieNode    TrieNode()    {        children = new TrieNode[ALPHABET_SIZE];        for(int i = 0; i < ALPHABET_SIZE; i++)            children[i] = null;                      isEndOfWord = false;    }}  // If not present, inserts key into trie// If the key is prefix of trie node, just// marks leaf nodestatic 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] = new TrieNode();          pCrawl = pCrawl.children[index];    }      // Mark last node as leaf    pCrawl.isEndOfWord = true;}  // Returns true if key presents in trie, else// falsestatic 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);}  // Returns true if string can be segmented// into space separated words, otherwise // returns falsestatic boolean wordBreak(String str, TrieNode root){    int size = str.length();      // Base case    if (size == 0)        return true;      // Try all prefixes of lengths from 1 to size    for(int i = 1; i <= size; i++)     {                  // The parameter for search is         // str.substring(0, i)         // str.substrinf(0, i) which is        // prefix (of input string) of         // length 'i'. We first check whether        // current prefix is in dictionary.         // Then we recursively check for remaining        // string str.substr(i, size) which         // is suffix of length size-i.        if (search(root, str.substring(0, i)) &&             wordBreak(str.substring(i, size), root))            return true;    }      // If we have tried all prefixes and none    // of them worked    return false;}  // Driver codepublic static void main(String []args){    String dictionary[] = { "mobile", "samsung",                            "sam", "sung", "ma",                            "mango", "icecream",                             "and", "go", "i", "like",                            "ice", "cream" };                                  int n = dictionary.length;    TrieNode root = new TrieNode();      // Construct trie    for(int i = 0; i < n; i++)        insert(root, dictionary[i]);      System.out.print(wordBreak("ilikesamsung", root) ?                               "Yes\n" : "No\n");    System.out.print(wordBreak("iiiiiiii", root) ?                                "Yes\n" : "No\n");    System.out.print(wordBreak("", root) ?                               "Yes\n" : "No\n");    System.out.print(wordBreak("ilikelikeimangoiii", root) ?                               "Yes\n" : "No\n");    System.out.print(wordBreak("samsungandmango", root) ?                               "Yes\n" : "No\n");    System.out.print(wordBreak("samsungandmangok", root) ?                               "Yes\n" : "No\n");}}  // This code is contributed by Ganeshchowdharysadanala
class Solution(object):    def wordBreak(self, s, wordDict):        """        Author : @amitrajitbose        :type s: str        :type wordDict: List[str]        :rtype: bool        """        """CREATING THE TRIE CLASS"""          class TrieNode(object):                          def __init__(self):                self.children = [] #will be of size = 26                self.isLeaf = False                          def getNode(self):                p = TrieNode() #new trie node                p.children = []                for i in range(26):                    p.children.append(None)                p.isLeaf = False                return p                          def insert(self, root, key):                key = str(key)                pCrawl = root                for i in key:                    index = ord(i)-97                    if(pCrawl.children[index] == None):                        # node has to be initialised                        pCrawl.children[index] = self.getNode()                    pCrawl = pCrawl.children[index]                pCrawl.isLeaf = True #marking end of word                          def search(self, root, key):                #print("Searching %s" %key) #DEBUG                pCrawl = root                for i in key:                    index = ord(i)-97                    if(pCrawl.children[index] == None):                        return False                    pCrawl = pCrawl.children[index]                if(pCrawl and pCrawl.isLeaf):                    return True                  def checkWordBreak(strr, root):            n = len(strr)            if(n == 0):                return True            for i in range(1,n+1):                if(root.search(root, strr[:i]) and checkWordBreak(strr[i:], root)):                    return True            return False                  """IMPLEMENT SOLUTION"""        root = TrieNode().getNode()        for w in wordDict:            root.insert(root, w)        out = checkWordBreak(s, root)        if(out):            return "Yes"        else:            return "No"  print(Solution().wordBreak("thequickbrownfox", ["the", "quick", "fox", "brown"]))print(Solution().wordBreak("bedbathandbeyond", ["bed", "bath", "bedbath", "and", "beyond"]))print(Solution().wordBreak("bedbathandbeyond", ["teddy", "bath", "bedbath", "and", "beyond"]))print(Solution().wordBreak("bedbathandbeyond", ["bed", "bath", "bedbath", "and", "away"]))
Output: 
Yes
Yes
Yes
Yes
Yes
No

This article is contributed by Pranav. The Python code has been contributed by Jeet9. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above. 
Jeet9
Ganeshchowdharysadanala
Trie
Strings
Strings
Trie
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Python program to check if a string is palindrome or not
Convert string to char array in C++
Longest Palindromic Substring | Set 1
Array of Strings in C++ (5 Different Ways to Create)
Caesar Cipher in Cryptography
Reverse words in a given string
Length of the longest substring without repeating characters
Check whether two strings are anagram of each other
Top 50 String Coding Problems for Interviews
How to split a string in C/C++, Python and Java?