Skip to content
Related Articles

Related Articles

Minimum Word Break

View Discussion
Improve Article
Save Article
  • Difficulty Level : Hard
  • Last Updated : 27 Jul, 2022
View Discussion
Improve Article
Save Article

Given a string s, break s such that every substring of the partition can be found in the dictionary. Return the minimum break needed. 

Examples: 

Given a dictionary ["Cat", "Mat", "Ca", 
     "tM", "at", "C", "Dog", "og", "Do"]

Input :  Pattern "CatMat"
Output : 1 
Explanation: we can break the sentences
in three ways, as follows:
CatMat = [ Cat Mat ]  break 1
CatMat = [ Ca tM at ] break 2
CatMat = [ C at Mat ] break 2  so the 
         output is: 1

Input : Dogcat
Output : 1

Asked in: Facebook 

Solution of this problem is based on the WordBreak Trie solution and level ordered graph. We start traversing given pattern and start finding a character of pattern in a trie. If we reach a node(leaf) of a trie from where we can traverse a new word of a trie(dictionary), we increment level by one and call search function for rest of the pattern character in a trie. In the end, we return minimum Break. 

  MinBreak(Trie, key, level, start = 0 )
  ....  If start == key.length()
      ...update min_break
  for i = start to keylength 
  ....If we found a leaf node in trie 
        MinBreak( Trie, key, level+1, i )

Below is the implementation of above idea 

C++




// C++ program to find minimum breaks needed
// to break a string in dictionary words.
#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 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 the key into the trie
// If the key is the prefix of trie node, just
// marks 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 last node as leaf
    pCrawl->isEndOfWord = true;
}
 
// function break the string into minimum cut
// such the every substring after breaking
// in the dictionary.
void minWordBreak(struct TrieNode* root,
          string key, int start, int* min_Break,
                                 int level = 0)
{
    struct TrieNode* pCrawl = root;
 
    // base case, update minimum Break
    if (start == key.length()) {       
        *min_Break = min(*min_Break, level - 1);
        return;
    }
 
    // traverse given key(pattern)
    int minBreak = 0;  
    for (int i = start; i < key.length(); i++) {
        int index = key[i] - 'a';
        if (!pCrawl->children[index])
            return;
 
        // if we find a condition were we can
        // move to the next word in a trie
        // dictionary
        if (pCrawl->children[index]->isEndOfWord)
            minWordBreak(root, key, i + 1,
                           min_Break, level + 1);
 
        pCrawl = pCrawl->children[index];
    }
}
 
// Driver program to test above functions
int main()
{
    string dictionary[] = { "Cat", "Mat",
   "Ca", "Ma", "at", "C", "Dog", "og", "Do" };
    int n = sizeof(dictionary) / sizeof(dictionary[0]);
    struct TrieNode* root = getNode();
 
    // Construct trie
    for (int i = 0; i < n; i++)
        insert(root, dictionary[i]);
    int min_Break = INT_MAX;
 
    minWordBreak(root, "CatMatat", 0, &min_Break, 0);
    cout << min_Break << endl;
    return 0;
}

Java




// Java program to find minimum breaks needed
// to break a string in dictionary words.
public class Trie {
 
TrieNode root = new TrieNode();
int minWordBreak = Integer.MAX_VALUE;
 
    // Trie node
    class TrieNode {
        boolean endOfTree;
        TrieNode children[] = new TrieNode[26];
        TrieNode(){
            endOfTree = false;
            for(int i=0;i<26;i++){
                children[i]=null;
            }
        }
    }
 
    // If not present, inserts a key into the trie
    // If the key is the prefix of trie node, just
    // marks leaf node
    void insert(String key){
        int length = key.length();
 
        int index;
 
        TrieNode pcrawl = root;
 
        for(int i = 0; i < length; i++)
        {
            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.endOfTree = true;
 
    }
 
    // function break the string into minimum cut
    // such the every substring after breaking
    // in the dictionary.
    void minWordBreak(String key)
    {
        minWordBreak = Integer.MAX_VALUE;
         
        minWordBreakUtil(root, key, 0, Integer.MAX_VALUE, 0);
    }
     
    void minWordBreakUtil(TrieNode node, String key,
                int start, int min_Break, int level)
    {
        TrieNode pCrawl = node;
 
        // base case, update minimum Break
        if (start == key.length()) {
            min_Break = Math.min(min_Break, level - 1);
            if(min_Break<minWordBreak){
                minWordBreak = min_Break;
            }
            return;
        }
 
        // traverse given key(pattern)
        for (int i = start; i < key.length(); i++) {
            int index = key.charAt(i) - 'a';
            if (pCrawl.children[index]==null)
                return;
 
            // if we find a condition were we can
            // move to the next word in a trie
            // dictionary
            if (pCrawl.children[index].endOfTree) {
                minWordBreakUtil(root, key, i + 1,
                        min_Break, level + 1);
 
            }
            pCrawl = pCrawl.children[index];
        }
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String keys[] = {"cat", "mat", "ca", "ma",
                    "at", "c", "dog", "og", "do" };
 
        Trie trie = new Trie();
 
        // Construct trie
         
        int i;
        for (i = 0; i < keys.length ; i++)
            trie.insert(keys[i]);
         
        trie.minWordBreak("catmatat");
 
        System.out.println(trie.minWordBreak);
    }
}
 
// This code is contributed by Pavan Koli.

C#




// C# program to find minimum breaks needed
// to break a string in dictionary words.
using System;
 
class Trie
{
 
    TrieNode root = new TrieNode();
    int minWordBreak = int.MaxValue ;
 
    // Trie node
    public class TrieNode
    {
        public bool endOfTree;
        public TrieNode []children = new TrieNode[26];
        public TrieNode()
        {
            endOfTree = false;
            for(int i = 0; i < 26; i++)
            {
                children[i] = null;
            }
        }
    }
 
    // If not present, inserts a key
    // into the trie If the key is the
    // prefix of trie node, just marks leaf node
    void insert(String key)
    {
        int length = key.Length;
 
        int index;
 
        TrieNode pcrawl = root;
 
        for(int i = 0; i < length; i++)
        {
            index = key[i]- 'a';
 
            if(pcrawl.children[index] == null)
                pcrawl.children[index] = new TrieNode();
 
            pcrawl = pcrawl.children[index];
        }
         
        // mark last node as leaf
        pcrawl.endOfTree = true;
 
    }
 
    // function break the string into minimum cut
    // such the every substring after breaking
    // in the dictionary.
    void minWordBreaks(String key)
    {
        minWordBreak = int.MaxValue;
        minWordBreakUtil(root, key, 0, int.MaxValue, 0);
    }
     
    void minWordBreakUtil(TrieNode node, String key,
                int start, int min_Break, int level)
    {
        TrieNode pCrawl = node;
 
        // base case, update minimum Break
        if (start == key.Length)
        {
            min_Break = Math.Min(min_Break, level - 1);
            if(min_Break < minWordBreak)
            {
                minWordBreak = min_Break;
            }
            return;
        }
 
        // traverse given key(pattern)
        for (int i = start; i < key.Length; i++)
        {
            int index = key[i] - 'a';
            if (pCrawl.children[index]==null)
                return;
 
            // if we find a condition were we can
            // move to the next word in a trie
            // dictionary
            if (pCrawl.children[index].endOfTree)
            {
                minWordBreakUtil(root, key, i + 1,
                        min_Break, level + 1);
            }
            pCrawl = pCrawl.children[index];
        }
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        String []keys = {"cat", "mat", "ca", "ma",
                    "at", "c", "dog", "og", "do" };
 
        Trie trie = new Trie();
 
        // Construct trie
        int i;
        for (i = 0; i < keys.Length ; i++)
            trie.insert(keys[i]);
         
        trie.minWordBreaks("catmatat");
        Console.WriteLine(trie.minWordBreak);
    }
}
 
// This code is contributed by 29AjayKumar

Javascript




<script>
 
// JavaScript program to find minimum breaks needed
// to break a string in dictionary words.
 
class TrieNode
{
    constructor()
    {
        this.endOfTree=false;
        this.children=new Array(26);
        for(let i=0;i<26;i++)
            this.children[i]=null;
    }
}
 
let root = new TrieNode();
let minWordBreak = Number.MAX_VALUE;
 
// If not present, inserts a key into the trie
    // If the key is the prefix of trie node, just
    // marks leaf node
function insert(key)
{
    let length = key.length;
   
        let index;
   
        let pcrawl = root;
   
        for(let i = 0; i < length; i++)
        {
            index = key[i].charAt(0)- 'a'.charAt(0);
   
            if(pcrawl.children[index] == null)
                pcrawl.children[index] = new TrieNode();
   
            pcrawl = pcrawl.children[index];
        }
           
        // mark last node as leaf
        pcrawl.endOfTree = true;
}
 
// function break the string into minimum cut
    // such the every substring after breaking
    // in the dictionary.
function _minWordBreak(key)
{
    minWordBreak = Number.MAX_VALUE;
           
    minWordBreakUtil(root, key, 0, Number.MAX_VALUE, 0);
}
 
function minWordBreakUtil(node,key,start,min_Break,level)
{
    let pCrawl = node;
   
        // base case, update minimum Break
        if (start == key.length) {
            min_Break = Math.min(min_Break, level - 1);
            if(min_Break<minWordBreak){
                minWordBreak = min_Break;
            }
            return;
        }
   
        // traverse given key(pattern)
        for (let i = start; i < key.length; i++) {
            let index = key[i].charAt(0) - 'a'.charAt(0);
            if (pCrawl.children[index]==null)
                return;
   
            // if we find a condition were we can
            // move to the next word in a trie
            // dictionary
            if (pCrawl.children[index].endOfTree) {
                minWordBreakUtil(root, key, i + 1,
                        min_Break, level + 1);
   
            }
            pCrawl = pCrawl.children[index];
        }
}
 
// Driver code
let keys=["cat", "mat", "ca", "ma",
                    "at", "c", "dog", "og", "do" ];
 
let i;
for (i = 0; i < keys.length ; i++)
    insert(keys[i]);
 
_minWordBreak("catmatat");
 
document.write(minWordBreak);
 
 
// This code is contributed by rag2127
 
</script>

Python3




# Python program to find minimum breaks needed
# to break a string in dictionary words.
 
import sys
 
 
class TrieNode:
 
    def __init__(self):
     
        self.endOfTree = False
        self.children = [None for i in range(26)]
         
 
 
root = TrieNode()
minWordBreak = sys.maxsize
 
# If not present, inserts a key into the trie
    # If the key is the prefix of trie node, just
    # marks leaf node
def insert(key):
 
    global root,minWordBreak
 
    length = len(key)
 
    pcrawl = root
 
    for i in range(length):
 
        index = ord(key[i])- ord('a')
 
        if(pcrawl.children[index] == None):
            pcrawl.children[index] = TrieNode()
        pcrawl = pcrawl.children[index]
         
        # mark last node as leaf
        pcrawl.endOfTree = True
 
# function break the string into minimum cut
# such the every substring after breaking
# in the dictionary.
def _minWordBreak(key):
 
    global minWordBreak
 
    minWordBreak = sys.maxsize
         
    minWordBreakUtil(root, key, 0, sys.maxsize, 0)
 
def minWordBreakUtil(node,key,start,min_Break,level):
 
    global minWordBreak,root
 
    pCrawl = node
 
    # base case, update minimum Break
    if (start == len(key)):
            min_Break = min(min_Break, level - 1)
            if(min_Break<minWordBreak):
                minWordBreak = min_Break
             
            return
         
 
    # traverse given key(pattern)
    for i in range(start,len(key)):
        index = ord(key[i]) - ord('a')
        if (pCrawl.children[index]==None):
            return
 
        # if we find a condition were we can
        # move to the next word in a trie
        # dictionary
        if (pCrawl.children[index].endOfTree):
            minWordBreakUtil(root, key, i + 1,min_Break, level + 1)
 
        pCrawl = pCrawl.children[index]
         
 
 
# Driver code
keys=["cat", "mat", "ca", "ma", "at", "c", "dog", "og", "do" ]
 
for i in range(len(keys)):
    insert(keys[i])
 
_minWordBreak("catmatat")
 
print(minWordBreak)
 
# This code is contributed by shinjanpatra

Output: 

2

 

Time Complexity : O(n**n)
Auxiliary Space: O(n)

This article is contributed by Aarti_Rathi. 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.


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!