648. Replace Words
At a Glance
- Topic: tries
- Pattern: Trie
- Difficulty: Medium
- Companies: Google, Amazon, Microsoft, Meta, Apple
- Frequency: Medium
- LeetCode: 648
Problem (one-liner)
You are given a list of roots (short strings) and a sentence of space-separated words. For each word, replace it with the shortest root in the dictionary that is a prefix of that word; if no root is a prefix, keep the word unchanged.
Recognition Cues
- Prefix replacement from a static dictionary
- Shortest matching prefix → walk the trie along the word and stop at the first terminal node on that path
- Building the trie once amortizes many lookups
Diagram
At-a-glance flow (replace with problem-specific Mermaid as you refine this note). camelCase node IDs; no spaces in IDs.
Loading diagram…
Approaches
- Scan all roots per word —
O(words * roots * L)— too slow at scale. - Sort roots by length then try shortest first —
O(R log R + words * L * something)— acceptable but trie is cleaner. - Trie — insert all roots, then each word walks until missing edge or hitting a root marker.
Optimal Solution
Go
package main
import "strings"
type Trie struct {
children [26]*Trie
isRoot bool
}
func (trie *Trie) insert(root string) {
node := trie
for index := range root {
offset := int(root[index] - 'a')
if node.children[offset] == nil {
node.children[offset] = &Trie{}
}
node = node.children[offset]
}
node.isRoot = true
}
func (trie *Trie) replaceWord(word string) string {
node := trie
for index := range word {
offset := int(word[index] - 'a')
if node.children[offset] == nil {
return word
}
node = node.children[offset]
if node.isRoot {
return word[:index+1]
}
}
return word
}
func replaceWords(roots []string, sentence string) string {
trie := &Trie{}
for _, root := range roots {
trie.insert(root)
}
words := strings.Fields(sentence)
for wordIndex := range words {
words[wordIndex] = trie.replaceWord(words[wordIndex])
}
return strings.Join(words, " ")
}JavaScript
class Trie {
constructor() {
this.children = new Map();
this.isRoot = false;
}
insert(rootWord) {
let node = this;
for (let index = 0; index < rootWord.length; index++) {
const letter = rootWord[index];
if (!node.children.has(letter)) {
node.children.set(letter, new Trie());
}
node = node.children.get(letter);
}
node.isRoot = true;
}
replaceWord(word) {
let node = this;
for (let index = 0; index < word.length; index++) {
const letter = word[index];
if (!node.children.has(letter)) {
return word;
}
node = node.children.get(letter);
if (node.isRoot) {
return word.slice(0, index + 1);
}
}
return word;
}
}
function replaceWords(roots, sentence) {
const trie = new Trie();
for (const rootWord of roots) {
trie.insert(rootWord);
}
return sentence
.split(' ')
.map((word) => trie.replaceWord(word))
.join(' ');
}Walkthrough
Roots ["cat","bat","rat"], sentence "the cattle was rattled by the battery".
| token | walk stops when | output |
|---|---|---|
the | no shared prefix early | the |
cattle | after cat terminal | cat |
rattled | after rat | rat |
battery | after bat | bat |
Invariant: descending one character at a time, the first node marked isRoot along the token’s prefix yields the shortest dictionary root by construction of the path length.
Edge Cases
- Root equals whole word → replacement identical
- One root is prefix of another — shorter root terminates walk first (insert order does not matter if trie marks both terminals at correct depths)
Pitfalls
- Returning the longest root instead of first hit — wrong problem interpretation
- Splitting sentence incorrectly on multiple spaces—
strings.FieldsvsSplit(match problem contract)
Similar Problems
- 208. Implement Trie — same trie core without sentence glue.
- 211. Design Add and Search Words Data Structure — richer matching rules.
- 1268. Search Suggestions System — prefix-driven completions.
Variants
- Replace with longest root instead — walk full word tracking last terminal seen.
- Case-insensitive or Unicode alphabets → change edge map.
Mind-Map Tags
#trie #prefix #replace #sentence #shortest-match
Last updated on
Spotted something unclear or wrong on this page?