Trie
Implementation
class TrieNode:
def __init__(self):
self.isWord = False
self.nodes = {}
class Trie:
def __init__(self):
self.root = TrieNode()
# Inserts a word into the trie.
def insert(self, word: str) -> None:
cur = self.root;
for c in word:
if c not in cur.nodes:
cur.nodes[c] = TrieNode()
cur = cur.nodes[c]
cur.isWord = True;
# Returns if the word is in the trie
def search(self, word: str) -> bool:
cur = self.root
for c in word:
if c not in cur.nodes:
return False
cur = cur.nodes[c]
return cur.isWord
# Returns if there is any word in the trie
# that starts with the given prefix. */
def startsWith(self, prefix: str) -> bool:
cur = self.root
for c in prefix:
if c not in cur.nodes:
return False
cur = cur.nodes[c]
return True
Without Class
trie = {}
for w in dictionary:
cur = trie
for ch in w:
cur = cur.setdefault(ch,{})
cur['$'] = w
def find(w):
cur = trie
for ch in w:
if ch not in cur:
return True
cur = cur[ch]
return cur.get('$', False):
Optimization: Pre Order Traversal
To find all words in sorted order, iterate the alphabet instead of sorting the words. Then we are guaranteed O(n) instead of O(nlogn) for the sort.
Practice Problems
- [[LC-1268. Search Suggestions System]]
- Preorder traversal of a trie
- Do not sort. Loop the alphabet instead
Replace Words
def replaceWords(self, dictionary: List[str], sentence: str) -> str:
trie = {}
for w in dictionary:
cur = trie
for ch in w:
cur = cur.setdefault(ch,{})
cur = cur[ch]
cur['$'] = w
def find(w):
cur = trie
for ch in w:
if ch not in cur:
return ''
cur = cur[ch]
if cur.get('$', ''):
return cur['$']
return ''
res = []
words = sentence.split(' ')
for w in words:
root = find(w)
if root:
res.append(root)
else:
res.append(w)
return ' '.join(res)
DP + Trie
Construct String with Minimum Cost
Construct target string from list of words with different costs
def minimumCost(self, target: str, words: List[str], costs: List[int]) -> int:
dp = [math.inf]*(len(target)+1)
dp[0] = 0
trie = {}
for w,cost in zip(words, costs):
node = trie
for c in w:
node.setdefault(c, {})
node = node[c]
node['$'] = min(cost, node.get('$', inf))
for i in range(len(target)):
node = trie
for j in range(i, len(target)):
c = target[j]
if c not in node:
break
node = node[c]
cost = node.get('$', 0)
if cost:
dp[j+1] = min(dp[j+1], dp[i] + cost)
return dp[-1] if dp[-1] != inf else -1