
Problem Statement
Given a non-empty string and a dictionary containing a list of non-empty words, determine if the string can be segmented into a space-separated sequence of one or more dictionary words. Each word in the dictionary can be reused multiple times.
Examples
Example 1:
- Input:
- String: "ilovecoding"
- Dictionary: ["i", "love", "coding"]
- Expected Output: True
- Justification: The string can be segmented as "i love coding".
Example 2:
- Input:
- String: "helloworld"
- Dictionary: ["hello", "world", "hell", "low"]
- Expected Output: True
- Justification: The string can be segmented as "hello world".
Example 3:
- Input:
- String: "enjoylife"
- Dictionary: ["enj", "life", "joy"]
- Expected Output: False
- Justification: Despite having the words "enj" and "life" in the dictionary, we can't segment the string into the space-separated dictionary words.
Constraints:
1 <= s.length <= 3001 <= wordDict.length <= 10001 <= wordDict[i].length <= 20sandwordDict[i]consist of only lowercase English letters.- All the strings of wordDict are unique.
Solution
Our algorithm's primary objective is to determine whether the given string can be broken down into a sequence of words present in the dictionary. To achieve this, we use a dynamic programming approach, maintaining an array to keep track of the possibility of forming valid sequences up to every index of the string. The primary idea is to iterate through the string and, at each step, check all possible word endings at the current position. If a valid word is found, and the starting position of that word was marked as achievable, we mark the current position as achievable too.
-
Initialization:
- Begin by initializing a boolean array
dpof sizen+1, wherenis the length of the string. This array will record whether the string can be segmented up to a certain index. We set the first element,dp[0], totruesince an empty string can always be segmented.
- Begin by initializing a boolean array
-
Dynamic Programming:
- Iterate over the length of the string. For each index
i, verify every substring ending atiand see if it exists in the dictionary. - If a valid word is found and the starting position (denoted as
dp[j]) of the substring is true, setdp[i+1]to true. - Proceed in this manner until you reach the end of the string.
- Iterate over the length of the string. For each index
-
Result:
- Once the iteration is complete, the value of
dp[n]will indicate if the entire string can be segmented into dictionary words or not.
- Once the iteration is complete, the value of
-
Optimization:
- For faster lookups, convert the word dictionary into a set. This ensures constant time complexity when searching for words in the dictionary.
Algorithm Walkthrough
Let's trace the second example, "helloworld" with ["hello", "world", "hell", "low"]. Move through the steps one at a time:
Step 1. Each cell asks one question: can everything up to this point be cut into words from the list? The empty prefix is reachable by definition, and every other yes grows out of that one. The rule has two halves and both must hold: a word from the list has to end at this position, and the position where that word starts has to be reachable already. Finding a matching word on its own proves nothing.
1 of 6
Code
Complexity Analysis
- Time Complexity: O(n^2) due to the two nested loops where we check all possible substrings.
- Space Complexity: O(n) for the DP array and the word set.