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.
Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!