-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathWordBreakBoolean.java
102 lines (81 loc) · 4.75 KB
/
WordBreakBoolean.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
https://www.geeksforgeeks.org/word-break-problem-dp-32/
https://leetcode.com/problems/word-break/discuss/43790/Java-implementation-using-DP-in-two-ways
NOTE - NOT SURE ABOUT THE TIME COMPLEXITY
Comment from Leetcode -
just want to add some comments for the time complexity:
First DP: [length of s][size of dict][avg length of words in dict]
Second DP: [length of s]^3
BTW, for this kind of problem, which time complexity is [length of s][size of dict][avg length of words in dict]. We can usually remove [size of dict] by using Tire, remove [avg length of words in dict] by KMP, and what's more, remove both [size of dict] and [avg length of words in dict] by AC-automata. And of course these are all doable for this problem.
This is just a insight for people who want to think deeper about this problem, hope it can help you :)
QUESTION -
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.
{ 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".
*/
//DP - Method 1
public boolean wordBreak(String s, Set<String> dict){
//T[i] indicates if it is possible to break the string s[0...i] into valid words from the dictionary
boolean T[] = new boolean[s.length()+1];
//i=0 indicates empty string, which is valid ==> true
T[0] = true;
//the string under consideration starts from length=1 and goes up to length=s.length()
//This is a bottom up approach - we start from the base condition ie. length=1
//During each iteration the string under consideration is s[0....i]
for(int i=1 ; i <= s.length() ; i++){
//j is used to create a partition
//The problem here is to check if s[0...i] can be broken down into valid words from the dictionary
//We need to find where to make a break to get a valid result ==> explore all breaking points using 'j'
//'j' breaks the string s[0...i] into two parts ==> s[0...j) and s[j...i)
//subproblem is s[0...j) which has already been solved and the result is stored in T[j]
//In this loop we basically -
//1. choose a partition index - j
//2. check if the suffix string is present in the dictionary
//3. If it is then check if the prefix can be broken into valid words from the dictionary
//4. If both 2 and 3 are true, we found another valid break of the string at index j, break as soon as 2 & 3 become true
//we start at j=0 because we want to check if the entire word s[0...i] is present in the dictionary or not
for(int j=0 ; j < i ; j++){
if(dict.contains(s.substring(j,i)) && T[j]){
T[i] = true;
break;
}
}
}
return T[s.length()];
}
//Time - O(n^2) OR O(n^3) ????
//DP-Method 2
public boolean wordBreak(String s, Set<String> dict){
//T[i] indicates if it is possible to break the string s[0...i] into valid words from the dictionary
boolean T[] = new boolean[s.length()+1];
//i=0 indicates empty string, which is valid ==> true
T[0] = true;
//the string under consideration starts from length=1 and goes up to length=s.length()
//This is a bottom up approach - we start from the base condition ie. length=1
//During each iteration the string under consideration is s[0....i]
for(int i=1 ; i<=s.length() ; i++){
//look through all the strings in the dictionary and see if any of these words fits as a suffix in the current string
for(String str : dict){
//1. To check if a string is present as a suffix we must first see if current 'i' ie. length of string under
//consideration is greater than the string from the dictionary
//2. If 1 is true we check if the string from dictionary matches with the suffix of string
//3. If 2 is true we solve the subproblem s[0......(i-str.length())] to see if this part of the string can be broken
/*
This code is exactly the same as the above - the inner for loop is used for partitioning in both the code snippets.
Here we use the dictionary string's length to partition
In the previous code a separate index is used to partition
*/
if(i >= str.length() && s.substring(i-str.length(),i).equals(str) && T[i-str.length()]){
T[i] = true;
break;
}
}
}
}
//Time - O(s.length()*dict.size())