class TrieNode {
children: Map<string, TrieNode> = new Map();
isWord: boolean = false;
}
class Trie {
root: TrieNode = new TrieNode();
insert(word: string): void {
let node = this.root;
for (const char of word) {
if (!node.children.has(char)) {
node.children.set(char, new TrieNode());
}
node = node.children.get(char)!;
}
node.isWord = true;
}
longestWord(): string {
let result = "";
const dfs = (node: TrieNode, path: string): void => {
if (node !== this.root && !node.isWord) return; // skip if prefix not a word
if (path.length > result.length || (path.length === result.length && path < result)) {
result = path;
}
for (const [char, child] of [...node.children.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
dfs(child, path + char);
}
};
dfs(this.root, "");
return result;
}
}
// Driver code
const words = ["a", "app", "apple", "apply", "ap", "appl"];
const trie = new Trie();
for (const word of words) {
trie.insert(word);
}
console.log(trie.longestWord());if (!node.children.has(char)) { node.children.set(char, new TrieNode()); }
Create new node if character path does not exist
node = node.children.get(char)!;
Advance node pointer to child node for next character
Mark current node as end of a valid word
if (node !== this.root && !node.isWord) return;
Stop DFS if current prefix is not a valid word
if (path.length > result.length || (path.length === result.length && path < result)) { result = path; }
Update longest word if current path is longer or lex smaller if tie
for (const [char, child] of [...node.children.entries()].sort((a, b) => a[0].localeCompare(b[0]))) { dfs(child, path + char); }
Traverse children in alphabetical order to ensure lex order