Word Break Problem | DP-32 | Set – 2
Last Updated :
23 Apr, 2023
Given a non-empty sequence S and a dictionary dict[] containing a list of non-empty words, print all possible ways to break the sentence in individual dictionary words.
Examples:
Input: S = “catsanddog”
dict[] = {“cat”, “cats”, “and”, “sand”, “dog”}
Output:
“cats and dog”
“cat sand dog”
Input: S = “pineapplepenapple”
dict[] = {“apple”, “pen”, “applepen”, “pine”, “pineapple”}
Output:
“pine apple pen apple”
“pineapple pen apple”
“pine applepen apple”
A similar problem to this is discussed in this article, where the task is to check that is there any solution such that the sequence can be broken into the dictionary words.
Approach: The idea is to check for every substring starting from any position I , such that it ends at the length of the string which is present in the dictionary then simply recurse for the substring [0, I]. Meanwhile, store the overlapping subproblems for each substring to avoid the computation of the subproblem again. Overlapping subproblems can be shown as follows –
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
unordered_map<string,
vector<string> > mp;
unordered_set<string> dict;
void printResult(vector<string> A)
{
for ( int i = 0; i < A.size(); i++)
cout << A[i] << '\n' ;
}
vector<string> combine(
vector<string> prev, string word){
for ( int i = 0; i < prev.size(); i++) {
prev[i] += " " + word;
}
return prev;
}
vector<string> wordBreakUtil(string s)
{
if (mp.find(s) != mp.end())
return mp[s];
vector<string> res;
if (dict.find(s) != dict.end())
res.push_back(s);
for ( int i = 1; i < s.length(); i++) {
string word = s.substr(i);
if (dict.find(word) != dict.end()) {
string rem = s.substr(0, i);
vector<string> prev =
combine(wordBreakUtil(rem), word);
res.insert(res.end(),
prev.begin(), prev.end());
}
}
mp[s] = res;
return res;
}
vector<string> wordBreak(string s,
vector<string>& wordDict)
{
mp.clear();
dict.clear();
dict.insert(wordDict.begin(), wordDict.end());
return wordBreakUtil(s);
}
int main()
{
vector<string> wordDict1 = {
"cat" , "cats" , "and" , "sand" , "dog" };
printResult(wordBreak( "catsanddog" , wordDict1));
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class GFG{
static TreeMap<String, ArrayList<String>> mp =
new TreeMap<String, ArrayList<String>>();
static TreeSet<String> dict = new TreeSet<String>();
static void printResult(ArrayList<String> A)
{
for ( int i = 0 ; i < A.size() ; i++){
System.out.println(A.get(i));
}
}
static ArrayList<String> combine(ArrayList<String> prev, String word){
for ( int i = 0 ; i < prev.size() ; i++) {
prev.set(i, prev.get(i) + " " + word);
}
return prev;
}
static ArrayList<String> wordBreakUtil(String s)
{
if (mp.containsKey(s)){
return mp.get(s);
}
ArrayList<String> res = new ArrayList<String>();
if (dict.contains(s))
res.add(s);
for ( int i = 1 ; i < s.length() ; i++) {
String word = s.substring(i);
if (dict.contains(word)) {
String rem = s.substring( 0 , i);
ArrayList<String> prev = combine(wordBreakUtil(rem), word);
for ( int j = 0 ; j < prev.size() ; j++){
res.add(prev.get(j));
}
}
}
mp.put(s, res);
return res;
}
static ArrayList<String> wordBreak(String s, ArrayList<String> wordDict)
{
mp.clear();
dict.clear();
dict.addAll(wordDict);
return wordBreakUtil(s);
}
public static void main(String args[])
{
ArrayList<String> wordDict1 = new ArrayList<String>(
List.of( "cat" , "cats" , "and" , "sand" , "dog" )
);
printResult(wordBreak( "catsanddog" , wordDict1));
}
}
|
Python3
mp = dict ()
dict_t = set ()
def printResult(A):
for i in range ( len (A)):
print (A[i])
def combine( prev, word):
for i in range ( len (prev)):
prev[i] + = " " + word;
return prev;
def wordBreakUtil(s):
if (s in mp):
return mp[s];
res = []
if (s in dict_t):
res.append(s);
for i in range ( 1 , len (s)):
word = s[i:];
if (word in dict_t):
rem = s[:i]
prev = combine(wordBreakUtil(rem), word);
for i in prev:
res.append(i)
x = []
for i in res:
x.append(i)
mp[s] = x;
return res;
def wordBreak(s, wordDict):
mp.clear();
dict_t.clear();
for i in wordDict:
dict_t.add(i)
return wordBreakUtil(s);
if __name__ = = '__main__' :
wordDict1 = [ "cat" , "cats" , "and" , "sand" , "dog" ]
printResult(wordBreak( "catsanddog" , wordDict1));
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static Dictionary< string , List< string >> mp = new Dictionary< string , List< string >>();
static HashSet< string > dict = new HashSet< string >();
static void printResult(List< string > A)
{
foreach ( string str in A)
{
Console.WriteLine(str);
}
}
static List< string > combine(List< string > prev, string word)
{
for ( int i = 0; i < prev.Count; i++)
{
prev[i] = prev[i] + " " + word;
}
return prev;
}
static List< string > wordBreakUtil( string s)
{
if (mp.ContainsKey(s))
{
return mp[s];
}
List< string > res = new List< string >();
if (dict.Contains(s))
res.Add(s);
for ( int i = 1; i < s.Length; i++)
{
string word = s.Substring(i);
if (dict.Contains(word))
{
string rem = s.Substring(0, i);
List< string > prev = combine(wordBreakUtil(rem), word);
for ( int j = 0; j < prev.Count; j++)
{
res.Add(prev[j]);
}
}
}
mp[s] = res;
return res;
}
static List< string > wordBreak( string s, List< string > wordDict)
{
mp.Clear();
dict.Clear();
dict.UnionWith(wordDict);
return wordBreakUtil(s);
}
static void Main( string [] args)
{
List< string > wordDict1 = new List< string >() { "cat" , "cats" , "and" , "sand" , "dog" };
printResult(wordBreak( "catsanddog" , wordDict1));
}
}
|
Javascript
<script>
let mp = new Map()
let dict_t = new Set()
function printResult(A){
for (let i=0;i<A.length;i++)
document.write(A[i], "</br>" )
}
function combine(prev, word){
for (let i=0;i<prev.length;i++)
prev[i] += " " + word;
return prev;
}
function wordBreakUtil(s){
if (mp.has(s))
return mp.get(s)
let res = []
if (dict_t.has(s))
res.push(s);
for (let i=1;i<s.length;i++){
let word = s.substring(i,)
if (dict_t.has(word)){
let rem = s.substring(0,i)
let prev = combine(wordBreakUtil(rem), word);
for (let i of prev)
res.push(i)
}
}
let x=[]
for (let i of res)
x.push(i)
mp.set(s, x)
return res
}
function wordBreak(s, wordDict){
mp.clear();
dict_t.clear();
for (let i of wordDict)
dict_t.add(i)
return wordBreakUtil(s);
}
let wordDict1 = [ "cat" , "cats" , "and" , "sand" , "dog" ];
printResult(wordBreak( "catsanddog" , wordDict1));
</script>
|
Output
cat sand dog
cats and dog
Time Complexity: O(2^N), where N is the length of the given string.
Auxiliary Space: O(S + N). where S is the sum of all characters of wordDict1.
C++
#include <bits/stdc++.h>
using namespace std;
vector<string> wordBreak( int n, unordered_set<string> Dict,
string s)
{
int l = s.length();
vector<vector<string> > dp(l);
for ( int i = 0; i < l; i++) {
vector<string> arr;
for ( int j = i + 1; j < l + 1; j++) {
if (Dict.find(s.substr(i, j - i)) != Dict.end())
arr.push_back(s.substr(i, j - i));
}
dp[i] = arr;
}
vector<vector<string> > sol(l);
for ( int i = l - 1; i >= 0; i--) {
vector<string> ans;
if (dp[i].size()) {
for ( auto word : dp[i]) {
if (i + word.length() == l)
ans.push_back(word);
else if (sol[i + word.length()].size()) {
for ( auto w : sol[i + word.length()])
ans.push_back(word + " " + w);
}
}
}
sol[i] = ans;
}
return sol[0];
}
void print(vector<string> ans)
{
for ( auto x : ans) {
cout << x << "\n" ;
}
}
int main()
{
int n = 5;
unordered_set<string> Dict(
{ "cats" , "cat" , "and" , "sand" , "dog" });
string s = "catsanddog" ;
print(wordBreak(n, Dict, s));
return 0;
}
|
Java
import java.util.*;
class GFG {
static List<String>
wordBreak( int n, HashSet<String> Dict, String s)
{
int l = s.length();
List<List<String> > dp = new ArrayList<>();
for ( int i = 0 ; i < l; i++) {
List<String> arr = new ArrayList<>();
for ( int j = i + 1 ; j < l + 1 ; j++) {
if (Dict.contains(s.substring(i, j)))
arr.add(s.substring(i, j));
}
dp.add(arr);
}
List<List<String> > sol = new ArrayList<>();
for ( int i = 0 ; i < l; i++) {
sol.add( new ArrayList<>());
}
for ( int i = l - 1 ; i >= 0 ; i--) {
List<String> ans = new ArrayList<>();
if (dp.get(i).size() != 0 ) {
for (String word : dp.get(i)) {
if (i + word.length() == l)
ans.add(word);
else if (sol.get(i + word.length())
.size()
!= 0 ) {
for (String w :
sol.get(i + word.length()))
ans.add(word + " " + w);
}
}
}
sol.set(i, ans);
}
return sol.get( 0 );
}
static void print(List<String> ans)
{
for (String x : ans) {
System.out.println(x);
}
}
public static void main(String[] args)
{
int n = 5 ;
List<String> words = Arrays.asList(
"cats" , "cat" , "and" , "sand" , "dog" );
HashSet<String> Dict = new HashSet<String>(words);
Dict.addAll(words);
String s = "catsanddog" ;
print(wordBreak(n, Dict, s));
}
}
|
Python3
def wordBreak(n, Dict , s):
l = len (s)
dp = [ 0 ] * l
for i in range (l):
arr = []
for j in range (i + 1 , l + 1 ):
if ( s[i:j] in Dict ):
arr.append(s[i:j])
dp[i] = arr
sol = [ 0 ] * l
for i in range (l - 1 , - 1 , - 1 ):
ans = []
if dp[i]:
for word in dp[i]:
if ( i + len (word) = = l):
ans.append(word)
elif ( sol[i + len (word)] ):
for w in sol[i + len (word)]:
ans.append(word + " " + w)
sol[i] = ans
return sol[ 0 ]
if __name__ = = '__main__' :
n = 5
Dict = { "cats" , "cat" , "and" , "sand" , "dog" }
s = "catsanddog"
print (wordBreak(n, Dict , s))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
public static List< string > wordBreak( int n, HashSet< string > Dict, string s)
{
int l = s.Length;
List<List< string >> dp = new List<List< string >>();
for ( int i = 0; i < l; i++)
{
List< string > arr = new List< string >();
for ( int j = i + 1; j < l + 1; j++)
{
if (Dict.Contains(s.Substring(i, j - i)))
{
arr.Add(s.Substring(i, j - i));
}
}
dp.Add(arr);
}
List<List< string >> sol = new List<List< string >>();
for ( int i = 0; i < l; i++)
{
sol.Add( new List< string >());
}
for ( int i = l - 1; i >= 0; i--)
{
List< string > ans = new List< string >();
if (dp[i].Count > 0)
{
foreach ( string word in dp[i])
{
if (i + word.Length == l)
{
ans.Add(word);
}
else if (sol[i + word.Length].Count > 0)
{
foreach ( string w in sol[i + word.Length])
{
ans.Add(word + " " + w);
}
}
}
}
sol[i] = ans;
}
return sol[0];
}
static void Main( string [] args)
{
int n = 5;
HashSet< string > Dict = new HashSet< string >{ "cats" , "cat" , "and" , "sand" , "dog" };
string s = "catsanddog" ;
List< string > result = wordBreak(n, Dict, s);
foreach ( string item in result)
{
Console.WriteLine(item);
}
}
}
|
Javascript
function wordBreak(n, Dict, s)
{
let l = s.length;
let dp = new Array(l).fill(0);
for (let i = 0; i < l; i++) {
let arr = [];
for (let j = i+1; j <= l; j++) {
if (Dict.has(s.slice(i, j))) {
arr.push(s.slice(i, j));
}
}
dp[i] = arr;
}
let sol = new Array(l).fill(0);
for (let i = l-1; i >= 0; i--) {
let ans = [];
if (dp[i].length > 0) {
for (let word of dp[i]) {
if (i + word.length === l) {
ans.push(word);
}
else if (sol[i + word.length]) {
for (let w of sol[i + word.length]) {
ans.push(word + " " + w);
}
}
}
}
sol[i] = ans;
}
return sol[0];
}
let n = 5;
let Dict = new Set([ "cats" , "cat" , "and" , "sand" , "dog" ]);
let s = "catsanddog" ;
document.write(wordBreak(n, Dict, s)[0]+ "<br>" +wordBreak(n, Dict, s)[1]);
|
Output
cat sand dog
cats and dog
Time complexity: The time complexity of this code is O(n^3 * k), where n is the length of the input string and k is the maximum length of a word in the dictionary. The nested loops for creating the dp array takes O(n^3 * k) time, and the loops for forming the final output takes O(n^2 * k) time.
Space complexity: The space complexity of this code is O(n^2 * k), where n is the length of the input string and k is the maximum length of a word in the dictionary. The dp array takes O(n^2 * k) space, and the final output vector takes O(n^2 * k) space in the worst case.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...