Word Break
Problem
The first line is a word s. The second line holds a dictionary of words separated by spaces. Print true if s can be cut into pieces so that every piece is a word of the dictionary (a dictionary word can be used many times), else false. Use dynamic programming: reachable[i] tells if the first i letters can be built.
Constraints
- 1 <= word length <= 1000
- 1 <= dictionary words <= 1000
Examples
Input
applepenapple apple pen
Output
true
Solutions
Greedy cutting fails (for leetcode the first piece could be a wrong one in other examples), and trying every way of cutting is exponential. The table reachable[] remembers for each prefix if it can be built, so each position is solved once: O(n^2) set lookups.
/*
* Problem : Can it be cut?
* Input : A word, then a dictionary line.
* Output : true or false.
* Approach: DP over the cut points.
* Time : O(n^2)
* Space : O(n)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// This method solves the task. It receives the input and returns the answer.
static boolean solve(String[] lines) {
// Step 1: Read the word and put the dictionary words in a set for fast lookup.
String word = lines[0];
java.util.Set<String> dictionary = new java.util.HashSet<>(java.util.Arrays.asList(lines[1].split(" ")));
// Step 2: reachable[i] is true when the first i letters can be cut into dictionary words. The empty start is reachable.
boolean[] reachable = new boolean[word.length() + 1];
reachable[0] = true;
for (int end = 1; end <= word.length(); end++) {
// Step 3: Try every cut point. The first part must be reachable and the rest must be a word.
for (int cut = 0; cut < end && !reachable[end]; cut++) {
if (reachable[cut] && dictionary.contains(word.substring(cut, end))) {
reachable[end] = true;
}
}
}
return reachable[word.length()];
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(solve(lines));
}
}
Hints (1)
- Why does a greedy longest-word-first cut fail?