{x}
blog image

Implement Trie II (Prefix Tree)

Solution Explanation for Implement Trie II (Prefix Tree)

This problem requires implementing a Trie data structure with additional functionalities to count words and prefixes, and to erase words. The solution uses a node-based approach where each node represents a character in a word.

Data Structure: Trie Node

Each node in the Trie consists of:

  • children: An array (or map) to store pointers to child nodes. The size of the array depends on the character set (26 for lowercase English letters). children[i] points to the node representing the (i+1)-th character in the alphabet.
  • v: An integer representing the number of words ending at this node.
  • pv: An integer representing the number of words having this node as a prefix.

Operations:

  1. insert(word):

    • Traverse the Trie using the characters of the word.
    • If a character's corresponding child node doesn't exist, create a new node and add it to the children array.
    • Increment pv for each node visited along the path.
    • Once the end of the word is reached, increment v for the final node to indicate a complete word.
  2. countWordsEqualTo(word):

    • Traverse the Trie following the characters of the word.
    • If the traversal reaches the end of the word, return the v value of the final node (number of times this exact word exists).
    • Otherwise (if a node is missing along the way), return 0.
  3. countWordsStartingWith(prefix):

    • Similar to countWordsEqualTo, but instead of checking the v value at the end, return the pv value of the last node reached in the prefix traversal. This represents all words starting with this prefix.
  4. erase(word):

    • Traverse the Trie using the characters of word.
    • Decrement pv for each node visited.
    • At the end of the word, decrement v for the final node.

Time and Space Complexity:

  • Time Complexity:

    • insert, countWordsEqualTo, countWordsStartingWith, erase: O(L), where L is the length of the word or prefix. This is because the operations involve traversing at most L nodes in the Trie.
  • Space Complexity:

    • O(N * L), where N is the number of words inserted and L is the average length of a word. In the worst case, the Trie could store all prefixes of all words, potentially using a lot of space. However, in practice, it's often much less than this worst-case scenario, especially if words share common prefixes.

Code Examples (Python, Java, C++, Go):

The code examples in the provided markdown demonstrate the implementation of the Trie with the above operations. They are well-structured and follow the algorithm explained above. The key is using the children array, v, and pv effectively to track word counts and prefixes. The search function is a helper function to efficiently navigate the Trie during operations.