InterviewPrepKit

Home / Coding / 1-D Dynamic Programming

Word Break

medium Original ↗
Solving tips
  • Index the DP by prefix length: dp[i] = 'can s[:i] be segmented' = any(dp[j] and s[j:i] in words for j<i).
  • Seed dp[0]=True (empty prefix) or every dp[i] stays False.
  • Put wordDict in a set for O(1) membership, and cap the inner cut-point loop by the longest word length to trim work.
  • Target roughly O(n^2 * L) time, O(n) space; break on the first valid split since you only need a boolean.

Problem

You are given a string s and a list of strings wordDict (a dictionary of allowed words, no duplicates). Decide whether s can be cut into a sequence of one or more pieces such that every piece is a word in wordDict. Words from the dictionary may be reused as many times as you like, and you do not have to use every dictionary word. Return True if such a segmentation exists, otherwise False.

Examples

  • s = "leetcode", wordDict = ["leet", "code"]True — split as "leet" + "code".
  • s = "applepenapple", wordDict = ["apple", "pen"]True — split as "apple" + "pen" + "apple"; "apple" is reused.
  • s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]False — every prefix decomposition leaves a suffix ("og", "andog", …) that cannot be completed.

Constraints

  • 1 <= len(s) <= 300
  • 1 <= len(wordDict) <= 1000
  • 1 <= len(word) <= 20 for each dictionary word
  • All strings are lowercase English letters.
  • The 300 length is small, but a naive “try every split” recursion explores exponentially many segmentations — the bound is chosen so that an O(n²)-ish DP passes and pure recursion times out.

Think about it first

Hint 1 Think about prefixes. If `s` is segmentable and its first word is `w`, then the remainder `s` with `w` stripped off the front must itself be segmentable. This "solve the smaller suffix" structure is what makes it a DP.
Hint 2 Define a boolean answer for each prefix length: can `s[:i]` be broken into dictionary words? `s[:i]` is breakable when there is some split point `j < i` where `s[:j]` is breakable AND the final chunk `s[j:i]` is a dictionary word. The empty prefix is breakable by definition.
Hint 3 Put the dictionary in a `set` for O(1) membership tests, then fill a `dp` array of size `n+1` from left to right: `dp[0] = True`, and `dp[i] = any(dp[j] and s[j:i] in words for j in range(i))`. The answer is `dp[n]`. You only ever need to test chunk lengths up to the longest dictionary word.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.