Check if the given string of words can be formed from words present in the dictionary

11 Jul, 2022
Given a string array of M words and a dictionary of N words. The task is to check if the given string of words can be formed from words present in the dictionary. 
Examples:
dict[] = { find, a, geeks, all, for, on, geeks, answers, inter } Input: str[] = { “find”, “all”, “answers”, “on”, “geeks”, “for”, “geeks” }; Output: YES all words of str[] are present in the dictionary so the output is YES
Input: str = {“find”, “a”, “geek”} Output: NO In str[], “find” and “a” were present in the dictionary but “geek” is not present in the dictionary so the output is NO
A naive Approach will be to match all words of the input sentence separately with each of the words in the dictionary and maintain a count of the number of occurrence of all words in the dictionary. So if the number of words in dictionary be n and no of words in the sentence be m this algorithm will take O(M*N) time. 
A better approach will be to use the modified version of the advanced data structure Trie the time complexity can be reduced to O(M * t) where t is the length of longest word in the dictionary which is lesser than n. So here a modification has been done to the trie node such that the isEnd variable is now an integer storing the count of occurrence of the word ending on this node. Also, the search function has been modified to find a word in the trie and once found decrease the count of isEnd of that node so that for multiple occurrences of a word in a sentence each is matched with a separate occurrence of that word in the dictionary.
Below is the illustration of the above approach:  
C++
Python3
// C++ program to check if a sentence// can be formed from a given set of words.#include <bits/stdc++.h>using namespace std;const int ALPHABET_SIZE = 26; // here isEnd is an integer that will store// count of words ending at that nodestruct trieNode {    trieNode* t[ALPHABET_SIZE];    int isEnd;}; // utility function to create a new nodetrieNode* getNode(){    trieNode* temp = new (trieNode);     // Initialize new node with null    for (int i = 0; i < ALPHABET_SIZE; i++)        temp->t[i] = NULL;    temp->isEnd = 0;    return temp;} // Function to insert new words in trievoid insert(trieNode* root, string key){    trieNode* trail;    trail = root;     // Iterate for the length of a word    for (int i = 0; i < key.length(); i++) {         // If the next key does not contains the character        if (trail->t[key[i] - 'a'] == NULL) {            trieNode* temp;            temp = getNode();            trail->t[key[i] - 'a'] = temp;        }        trail = trail->t[key[i] - 'a'];    }     // isEnd is increment so not only the word but its count is also stored    (trail->isEnd)++;}// Search function to find a word of a sentencebool search_mod(trieNode* root, string word){    trieNode* trail;    trail = root;     // Iterate for the complete length of the word    for (int i = 0; i < word.length(); i++) {         // If the character is not present then word        // is also not present        if (trail->t[word[i] - 'a'] == NULL)            return false;         // If present move to next character in Trie        trail = trail->t[word[i] - 'a'];    }     // If word foundthen decrement count of the word    if ((trail->isEnd) > 0 && trail != NULL) {        // if the word is found decrement isEnd showing one        // occurrence of this word is already taken so        (trail->isEnd)--;        return true;    }    else        return false;}// Function to check if string can be// formed from the sentencevoid checkPossibility(string sentence[], int m, trieNode* root){    int flag = 1;     // Iterate for all words in the string    for (int i = 0; i < m; i++) {         if (search_mod(root, sentence[i]) == false) {             // if a word is not found in a string then the            // sentence cannot be made from this dictionary of words            cout << "NO";             return;        }    }     // If possible    cout << "YES";} // Function to insert all the words of dictionary in the Trievoid insertToTrie(string dictionary[], int n,                  trieNode* root){     for (int i = 0; i < n; i++)        insert(root, dictionary[i]);} // Driver Codeint main(){    trieNode* root;    root = getNode();     // Dictionary of words    string dictionary[] = { "find", "a", "geeks",                            "all", "for", "on",                            "geeks", "answers", "inter" };    int N = sizeof(dictionary) / sizeof(dictionary[0]);     // Calling Function to insert words of dictionary to tree    insertToTrie(dictionary, N, root);     // String to be checked    string sentence[] = { "find", "all", "answers", "on",                          "geeks", "for", "geeks" };     int M = sizeof(sentence) / sizeof(sentence[0]);     // Function call to check possibility    checkPossibility(sentence, M, root);     return 0;}
# Python3 program to check if a sentence# can be formed from a given set of words.#include <bits/stdc++.h> ALPHABET_SIZE = 26;  # here isEnd is an integer that will store# count of words ending at that nodeclass trieNode:         def __init__(self):                 self.t = [None for i in range(ALPHABET_SIZE)]        self.isEnd = 0      # utility function to create a new nodedef getNode():     temp = trieNode()    return temp;  # Function to insert new words in triedef insert(root, key):     trail = None    trail = root;      # Iterate for the length of a word    for i in range(len(key)):          # If the next key does not contains the character        if (trail.t[ord(key[i]) - ord('a')] == None):            temp = None            temp = getNode();            trail.t[ord(key[i]) - ord('a')] = temp;                 trail = trail.t[ord(key[i]) - ord('a')];      # isEnd is increment so not only    # the word but its count is also stored    (trail.isEnd) += 1 # Search function to find a word of a sentencedef search_mod(root, word):     trail = root;      # Iterate for the complete length of the word    for i in range(len(word)):          # If the character is not present then word        # is also not present        if (trail.t[ord(word[i]) - ord('a')] == None):            return False;          # If present move to next character in Trie        trail = trail.t[ord(word[i]) - ord('a')];      # If word found then decrement count of the word    if ((trail.isEnd) > 0 and trail != None):               # if the word is found decrement isEnd showing one        # occurrence of this word is already taken so        (trail.isEnd) -= 1        return True;      else:        return False; # Function to check if string can be# formed from the sentencedef checkPossibility(sentence, m, root):    flag = 1;      # Iterate for all words in the string    for i in range(m):          if (search_mod(root, sentence[i]) == False):              # if a word is not found in a string then the            # sentence cannot be made from this dictionary of words            print('NO', end='')              return;      # If possible    print('YES')      # Function to insert all the words of dict in the Triedef insertToTrie(dictionary, n, root):    for i in range(n):        insert(root, dictionary[i]);  # Driver Codeif __name__=='__main__':         root = getNode();      # Dictionary of words    dictionary = [ "find", "a", "geeks",                            "all", "for", "on",                            "geeks", "answers", "inter" ]         N = len(dictionary)      # Calling Function to insert words of dictionary to tree    insertToTrie(dictionary, N, root);      # String to be checked    sentence = [ "find", "all", "answers", "on",                          "geeks", "for", "geeks" ]      M = len(sentence)      # Function call to check possibility    checkPossibility(sentence, M, root);  # This code is contributed by pratham76
YES
 
An efficient approach will be to use map. Keep the count of words in the map, iterate in the string and check if the word is present in the map. If present, then decrease the count of the word in the map. If it is not present, then it is not possible to make the given string from the given dictionary of words. 
Below is the implementation of above approach :  
C++
Java
Python3
C#
Javascript
// C++ program to check if a sentence// can be formed from a given set of words.#include <bits/stdc++.h>using namespace std; // Function to check if the word// is in the  dictionary or notbool match_words(string dictionary[], string sentence[],                 int n, int m){    // map to store all words in    // dictionary with their count    unordered_map<string, int> mp;     // adding all words in map    for (int i = 0; i < n; i++) {        mp[dictionary[i]]++;    }     // search in map for all    // words in the sentence    for (int i = 0; i < m; i++) {        if (mp[sentence[i]])            mp[sentence[i]] -= 1;        else            return false;    }     // all words of sentence are present    return true;} // Driver Codeint main(){    string dictionary[] = { "find", "a", "geeks",                            "all", "for", "on",                            "geeks", "answers", "inter" };     int n = sizeof(dictionary) / sizeof(dictionary[0]);     string sentence[] = { "find", "all", "answers", "on",                          "geeks", "for", "geeks" };     int m = sizeof(sentence) / sizeof(sentence[0]);     // Calling function to check if words are    // present in the dictionary or not    if (match_words(dictionary, sentence, n, m))        cout << "YES";    else        cout << "NO";     return 0;}
// Java program to check if a sentence// can be formed from a given set of words.import java.util.*; class GFG{ // Function to check if the word// is in the dictionary or notstatic boolean match_words(String dictionary[], String sentence[],                                                    int n, int m){    // map to store all words in    // dictionary with their count    Map<String,Integer> mp = new HashMap<>();     // adding all words in map    for (int i = 0; i < n; i++)    {        if(mp.containsKey(dictionary[i]))        {            mp.put(dictionary[i], mp.get(dictionary[i])+1);        }        else        {            mp.put(dictionary[i], 1);        }    }     // search in map for all    // words in the sentence    for (int i = 0; i < m; i++)    {        if (mp.containsKey(sentence[i]))            mp.put(sentence[i],mp.get(sentence[i])-1);        else            return false;    }     // all words of sentence are present    return true;} // Driver Codepublic static void main(String[] args){    String dictionary[] = { "find", "a", "geeks",                            "all", "for", "on",                            "geeks", "answers", "inter" };     int n = dictionary.length;     String sentence[] = { "find", "all", "answers", "on",                        "geeks", "for", "geeks" };     int m = sentence.length;     // Calling function to check if words are    // present in the dictionary or not    if (match_words(dictionary, sentence, n, m))        System.out.println("YES");    else        System.out.println("NO");    }} // This code is contributed by Princi Singh
# Python3 program to check if a sentence# can be formed from a given set of words. # Function to check if the word# is in the dictionary or notdef match_words(dictionary, sentence, n, m):         # map to store all words in    # dictionary with their count    mp = dict()     # adding all words in map    for i in range(n):        mp[dictionary[i]] = mp.get(dictionary[i], 0) + 1     # search in map for all    # words in the sentence    for i in range(m):        if (mp[sentence[i]]):            mp[sentence[i]] -= 1        else:            return False     # all words of sentence are present    return True # Driver Codedictionary = ["find", "a", "geeks", "all", "for",              "on", "geeks", "answers", "inter"] n = len(dictionary) sentence = ["find", "all", "answers", "on",            "geeks", "for", "geeks"] m = len(sentence) # Calling function to check if words are# present in the dictionary or notif (match_words(dictionary, sentence, n, m)):    print("YES")else:    print("NO") # This code is contributed by mohit kumar
// C# program to check if a sentence// can be formed from a given set of words.using System;using System.Collections.Generic;     class GFG{ // Function to check if the word// is in the dictionary or notstatic Boolean match_words(String []dictionary,                           String []sentence,                           int n, int m){    // map to store all words in    // dictionary with their count    Dictionary<String,               int> mp = new Dictionary<String,                                        int>();     // adding all words in map    for (int i = 0; i < n; i++)    {        if(mp.ContainsKey(dictionary[i]))        {            mp[dictionary[i]] = mp[dictionary[i]] + 1;        }        else        {            mp.Add(dictionary[i], 1);        }    }     // search in map for all    // words in the sentence    for (int i = 0; i < m; i++)    {        if (mp.ContainsKey(sentence[i]) && mp[sentence[i]] > 0)            mp[sentence[i]] = mp[sentence[i]] - 1;        else            return false;    }     // all words of sentence are present    return true;} // Driver Codepublic static void Main(String[] args){    String []dictionary = { "find", "a", "geeks",                            "all", "for", "on",                            "geeks", "answers", "inter" };     int n = dictionary.Length;     String []sentence = { "find", "all", "answers", "on",                          "geeks", "for", "geeks", "geeks" };     int m = sentence.Length;     // Calling function to check if words are    // present in the dictionary or not    if (match_words(dictionary, sentence, n, m))        Console.WriteLine("YES");    else        Console.WriteLine("NO");}} // This code is contributed by Rajput-Ji
<script> // Javascript program to check if a sentence// can be formed from a given set of words. // Function to check if the word// is in the  dictionary or not   function match_words(dictionary, sentence, n, m){         // map to store all words in    // dictionary with their count    let mp = new Map();         // Adding all words in map    for(let i = 0; i < n; i++)    {        if(mp.has(dictionary[i]))        {            mp.set(dictionary[i],            mp.get(dictionary[i]) + 1);        }        else        {            mp.set(dictionary[i], 1);        }    }         // Search in map for all    // words in the sentence    for(let i = 0; i < m; i++)    {        if (mp.has(sentence[i]))            mp.set(sentence[i],            mp.get(sentence[i]) - 1);        else            return false;    }         // All words of sentence are present    return true;} // Driver codelet dictionary = [ "find", "a", "geeks",                   "all", "for", "on",                   "geeks", "answers", "inter" ]; let n = dictionary.length; let sentence = [ "find", "all", "answers", "on",                 "geeks", "for", "geeks" ]; let m = sentence.length; // Calling function to check if words are// present in the dictionary or notif (match_words(dictionary, sentence, n, m))    document.write("YES");else    document.write("NO"); // This code is contributed by patel2127 </script>
YES
 
Time Complexity: O(M)Space Complexity: O(N) where N is no of words in a dictionary
mohit kumar 29
princi singh
Rajput-Ji
pratham76
arorakashish0911
patel2127
hrawat0022
technophpfij
C-String-Question
cpp-map
Searching Quiz
Trie
Advanced Data Structure
Strings
Strings
Trie
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.