The Vocabulary Test
A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- medium
- Seniority
- L4
- Asked in
Problem
A search-indexing step normalizes raw queries by checking whether a string s can be rebuilt as a gapless, back-to-back run of terms drawn from an approved vocabulary word_dict, reusing any term as many times as needed. Return whether at least one such full reconstruction exists with no characters left over; an empty s qualifies trivially.
Every character has to come from a word you already know.
Example 1
Input:
s = "leetcode", word_dict = ["leet","code"]
Output:
true
Example 2
Input:
s = "applepenapple", word_dict = ["apple","pen"]
Output:
true
Worked solution and explanation
What this really is
Strip off the vocabulary costume and this is a reachability question over the string's positions: can you walk from index 0 to the end, each hop consuming a chunk that happens to be a known word? The skill being probed is whether you resist the urge to greedily grab a word and commit to it. Take the longest match at each step and you will confidently return the wrong answer on inputs where a shorter early word was the only path that survives to the end.
Building it
Step 1: Put the vocabulary in a set
Membership is the inner-loop hot path, so pay the one-time cost to turn word_dict into a set. A list check is O(k) per probe and you do O(n^2) probes; the set makes each one O(1).
Step 2: Fill the reachability table left to right
Seed reachable[0] = True: the empty prefix is always coverable, which is also why an empty s returns True for free. Then for each end position, scan every earlier start; if that start was reachable and the slice between them is a word, this end is reachable too. Break the inner scan the instant you mark it, since one witness is enough.
Step 3: Read the last cell
The answer is simply whether the final position is reachable. reachable[len(s)] being True means some chain of words consumed the whole string with nothing left over.
The solution
def word_break_check(s: str, word_dict: list) -> bool:
vocab = set(word_dict)
n = len(s)
reachable = [False] * (n + 1)
reachable[0] = True
for end in range(1, n + 1):
for start in range(end):
if reachable[start] and s[start:end] in vocab:
reachable[end] = True
break
return reachable[n]Each end position opens as soon as one reachable start can hop to it.
- Greedy longest-match
- Pick the longest word at each cursor and advance. Fast and intuitive, but a single early commitment can dead-end a string that was actually segmentable a different way. No clean way to recover without backtracking.
- Reachability table
- Keep every reachable position alive at once. No commitment to undo, the whole search is two loops and a slice, and the answer falls out of the last cell. Same worst-case work, none of the wrong answers.
Common follow-up questions
- Now return every valid way to split the string, not just whether one exists. (Pushes from a boolean table to enumerating paths, usually memoized backtracking.)
- The vocabulary is millions of words. What changes? (Tests prefix-structured lookup; a Trie prunes the inner scan instead of probing all substrings.)
- How does this map onto subword tokenization in NLP? (Tests recognizing this segmentation is exactly how BPE-style tokenizers cover text with a fixed vocabulary.)