Bird
Raised Fist0
Interview PreptrieshardAmazonGoogleFacebook

Concatenated Words

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize Trie Root

Create the root node of the trie, which is empty and has no children or word end marker.

💡 The root node is the starting point for all word insertions and searches, representing an empty prefix.
Line:root = TrieNode()
💡 The trie starts empty, ready to build from the input words.
📊
Concatenated Words - Watch the Algorithm Execute, Step by Step
Watching each step of trie construction and DFS traversal reveals how the algorithm efficiently finds concatenated words by reusing prefix information and pruning redundant searches.
Step 1/15
·Active fill★Answer cell
insert
insert
cat
c
insert
cat
ca
insert
cat
cat*
insert
cats
cat*s*
search
catsdogcats
cat*s*dog*hipporat*
search
catsdogcats
cat*s*
search
catsdogcats
dog*
search
catsdogcats
dog*
search
catsdogcats
cat*s*
search
catsdogcats
cat*s*
Search: true
search
cat*s*dog*hipporat*
search
dogcatsdog
Search: true
search
ratcatdogcat
Search: true
search
cat*s*dog*hipporat*

Key Takeaways

✓ Trie structure efficiently stores all words sharing prefixes, enabling fast prefix checks during DFS.

This is hard to see from code alone because the trie structure is implicit; visualization shows how nodes and edges represent prefixes.

✓ DFS with memoization breaks down the concatenation problem into smaller subproblems, avoiding repeated work.

Memoization's effect is subtle in code but clear in visualization as repeated indices are skipped.

✓ Temporarily disabling the current word's end marker prevents counting the word itself as a concatenation, ensuring correctness.

This subtle trick is easy to miss in code but critical for correct results, and visualization highlights this step.

Practice

(1/5)
1. Given the following code snippet implementing the optimal trie-based solution, what is the output of replaceWords(['cat', 'bat', 'rat'], 'the cattle was rattled by the battery')?
easy
A. the cat was rat by the battery
B. the cat was rat by the bat
C. the cattle was rat by the battery
D. the cat was rattled by the battery

Solution

  1. Step 1: Trace prefix search for 'cattle'

    Check 'c' -> 'a' -> 't' in trie; 'cat' is a root and shortest prefix, so replace 'cattle' with 'cat'.
  2. Step 2: Trace prefix search for 'rattled' and 'battery'

    'rattled' matches 'rat' prefix; 'battery' matches 'bat' prefix. Other words have no prefix match and remain unchanged.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    All replaced words correspond to shortest root prefixes [OK]
Hint: Shortest prefix found stops search early [OK]
Common Mistakes:
  • Replacing with longer prefix
  • Not replacing words without prefix
2. Examine the following buggy search method for the WordDictionary implemented with a trie. Which line contains the subtle bug that causes incorrect search results for patterns with '.' wildcard?
def search(self, word: str) -> bool:
    stack = [(0, self.root)]
    while stack:
        index, node = stack.pop()
        if index == len(word):
            if node.is_end:
                return True
            continue
        ch = word[index]
        if ch == '.':
            for child in node.children:
                stack.append((index + 1, child))
        else:
            if ch in node.children:
                stack.append((index + 1, node.children[ch]))
    return False
medium
A. Line with 'stack = [(0, self.root)]'
B. Line with 'for child in node.children:'
C. Line with 'if node.is_end:'
D. Line with 'if ch in node.children:'

Solution

  1. Step 1: Identify how children are iterated for '.' wildcard

    The code uses 'for child in node.children:', which iterates over keys (characters), not child nodes.
  2. Step 2: Understand impact of iterating keys instead of nodes

    Appending keys instead of TrieNode objects causes incorrect stack entries and search failure.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Must iterate over node.children.values() to get child nodes [OK]
Hint: Iterate node.children.values(), not keys [OK]
Common Mistakes:
  • Iterating keys instead of child nodes
  • Forgetting to mark is_end
  • Misplacing base case check
3. What is the time complexity of the optimal trie-based solution to replace words in a sentence, where m is the number of words in the sentence and k is the average length of each word, assuming the trie is already built from n root words with average length l?
medium
A. O(n * l + m * k) because building the trie takes O(n * l) and searching each word takes O(k)
B. O(m * k) because each word is searched character by character in the trie until a prefix is found or word ends
C. O(m * k * l) because for each word, the trie traversal depends on both word and root lengths
D. O(m * n * l) because each word is compared against all roots in the trie

Solution

  1. Step 1: Identify trie construction cost

    Building the trie from n roots each of length l takes O(n * l) time.
  2. Step 2: Identify search cost per word

    Searching each of the m words of length k in the trie takes O(k) time per word.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Sum of build and search times matches O(n*l + m*k) [OK]
Hint: Trie build and search costs add up [OK]
Common Mistakes:
  • Assuming O(m*n*l) like brute force
  • Multiplying k and l unnecessarily
4. What is the time complexity of the optimal Trie + DFS solution for Word Search II, assuming the board has N cells, the maximum word length is L, and there are W words in the list?
medium
A. O(W * N * 4^L) -- checking each word independently with DFS
B. O(N * L) -- linear in board size and max word length due to Trie traversal
C. O(N * 4^L) -- DFS from each cell with pruning by Trie prefixes
D. O(W * L) -- building Trie and searching each word once

Solution

  1. Step 1: Identify DFS calls from each cell

    DFS explores up to 4 directions per step, up to length L, so worst-case 4^L paths per cell.
  2. Step 2: Consider Trie pruning

    Trie pruning cuts many paths early, but worst-case still O(N * 4^L) in theory.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Brute force per word is O(W * N * 4^L), which is much worse [OK]
Hint: Trie pruning reduces but worst-case DFS is exponential in L [OK]
Common Mistakes:
  • Confusing W factor in complexity
  • Ignoring exponential DFS branching
  • Assuming linear time due to Trie
5. Suppose you want to extend the Trie to support deletion of words. Which of the following approaches correctly handles deletion without breaking prefix searches for other words?
hard
A. Remove the isEnd flag at the last node of the word and delete nodes bottom-up only if they have no children and isEnd is false
B. Delete all nodes corresponding to the word immediately, regardless of children
C. Set isEnd to false at the last node but never delete any nodes
D. Rebuild the entire trie after each deletion to remove unused nodes

Solution

  1. Step 1: Understand deletion impact

    Removing isEnd flag marks word as deleted. Nodes can be deleted only if they are not prefixes of other words.
  2. Step 2: Delete nodes bottom-up conditionally

    Delete nodes only if they have no children and isEnd is false to avoid breaking other words.
  3. Step 3: Avoid unsafe deletions

    Deleting nodes immediately or rebuilding trie is inefficient or breaks other words.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Conditional bottom-up deletion preserves trie correctness [OK]
Hint: Delete nodes only if no children and isEnd is false [OK]
Common Mistakes:
  • Deleting nodes without checking children breaks other words
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard