Open In App

Count the number of words with given prefix using Trie

Prerequisite: Trie 

Given a list of string str[] and a prefix string pre. The task is to count the number of words in the list of string with a given prefix using trie.



Examples: 

Input: str = [ “apk”, “app”, “apple”, “arp”, “array” ], pre = “ap” 
Output:
Explanation: 
Below is the representation of trie from using above string. 
 



The words in str having prefix “ap” are apk, app and apple
So, the count is 3

Input: str = [ “gee”, “geek”, “geezer”, “geeksforgeeks”, “geekiness”, “geekgod” ], pre = “geek” 
Output:

Approach: 
To solve this problem Trie Data Structure is used and each node of this Trie contains the following three fields:  

  1. children: This field is used for mapping from a character to the next level trie node
  2. isEndOfWord: This field is used to distinguish the node as the end of the word node
  3. num: This field is used to count the number of times a node is visited during insertion in trie

Steps: 

Below is the implementation of the above approach:  




// C++ implementation of counting the
// number of words in a trie with a
// given prefix
#include "bits/stdc++.h"
using namespace std;
 
// Trie Node
struct TrieNode {
 
    // Using map to store the pointers
    // of children nodes for dynamic
    // implementation, for making the
    // program space efficient
    map<char, TrieNode*> children;
 
    // If isEndOfWord is true, then
    // node represents end of word
    bool isEndOfWord;
 
    // num represents number of times
    // a character has appeared during
    // insertion of the words in the
    // trie
    map<char, int> num;
};
 
// Declare root node
struct TrieNode* root;
 
// Function to create New Trie Node
struct TrieNode* getNewTrieNode()
{
    struct TrieNode* pNode = new TrieNode;
    pNode->isEndOfWord = false;
    return pNode;
}
 
// Function to insert a string in trie
void insertWord(string word)
{
    // To hold the value of root
    struct TrieNode* current = root;
 
    // To hold letters of the word
    char s;
 
    // Traverse through strings in list
    for (int i = 0; i < word.length(); i++) {
        s = word[i];
 
        // If s is not present in the
        // character field of current node
        if (current->children.find(s)
            == current->children.end()) {
 
            // Get new node
            struct TrieNode* p = getNewTrieNode();
 
            // Insert s in character
            // field of current node
            // with reference to node p
            (current->children)[s] = p;
 
            // Insert s in num field
            // of current node with
            // value 1
            (current->num)[s] = 1;
        }
        else {
 
            // Increment the count
            // corresponding to the
            // character s
            current->num[s] = (current->num)[s] + 1;
        }
 
        // Go to next node
        current = (current->children)[s];
    }
    current->isEndOfWord = true;
}
 
// Function to count the number of
// words in trie with given prefix
int countWords(vector<string>& words,
               string prefix)
{
    root = getNewTrieNode();
 
    // Size of list of string
    int n = words.size();
 
    // Construct trie containing
    // all the words
    for (int i = 0; i < n; i++) {
        insertWord(words[i]);
    }
 
    struct TrieNode* current = root;
    char s;
 
    // Initialize the wordCount = 0
    int wordCount = 0;
 
    for (int i = 0; prefix[i]; i++) {
        s = prefix[i];
 
        // If the complete prefix is
        // not present in the trie
        if (current->children.find(s)
            == current->children.end()) {
 
            // Make wordCount 0 and
            // break out of loop
            wordCount = 0;
            break;
        }
 
        // Update the wordCount
        wordCount = (current->num)[s];
 
        // Go to next node
        current = (current->children)[s];
    }
 
    return wordCount;
}
 
// Driver Code
int main()
{
    // input list of words
    vector<string> words;
    words = { "apk", "app", "apple",
              "arp", "array" };
 
    // Given prefix to find
    string prefix = "ap";
 
    // Print the number of words with
    // given prefix
    cout << countWords(words, prefix);
    return 0;
}




// Java implementation of counting the
// number of words in a trie with a
// given prefix
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
 
// Trie Node
class TrieNode
{
 
  // Using map to store the pointers
  // of children nodes for dynamic
  // implementation, for making the
  // program space efficient
  Map<Character, TrieNode> children;
 
  // If isEndOfWord is true, then
  // node represents end of word
  boolean isEndOfWord;
 
  // num represents number of times
  // a character has appeared during
  // insertion of the words in the
  // trie
  Map<Character, Integer> num;
 
  public TrieNode() {
    this.children = new HashMap<>();
    this.isEndOfWord = false;
    this.num = new HashMap<>();
  }
}
 
public class Main {
  // Declare root node
  static TrieNode root;
 
  // Function to create New Trie Node
  static TrieNode getNewTrieNode() {
    TrieNode pNode = new TrieNode();
    pNode.isEndOfWord = false;
    return pNode;
  }
 
  // Function to insert a string in trie
  static void insertWord(String word) {
    // To hold the value of root
    TrieNode current = root;
 
    // To hold letters of the word
    char s;
 
    // Traverse through strings in list
    for (int i = 0; i < word.length(); i++) {
      s = word.charAt(i);
 
      // If s is not present in the
      // character field of current node
      if (!current.children.containsKey(s)) {
        // Get new node
        TrieNode p = getNewTrieNode();
 
        // Insert s in character
        // field of current node
        // with reference to node p
        current.children.put(s, p);
 
        // Insert s in num field
        // of current node with
        // value 1
        current.num.put(s, 1);
      }
      else {
        // Increment the count
        // corresponding to the
        // character s
        current.num.put(s, current.num.get(s) + 1);
      }
 
      // Go to next node
      current = current.children.get(s);
    }
    current.isEndOfWord = true;
  }
 
  // Function to count the number of
  // words in trie with given prefix
  static int countWords(Vector<String> words, String prefix) {
    root = getNewTrieNode();
 
    // Size of list of string
    int n = words.size();
 
    // Construct trie containing
    // all the words
    for (int i = 0; i < n; i++) {
      insertWord(words.get(i));
    }
 
    TrieNode current = root;
    char s;
 
    // Initialize the wordCount = 0
    int wordCount = 0;
 
    for (int i = 0; i < prefix.length(); i++) {
      s = prefix.charAt(i);
 
      // If the complete prefix is
      // not present in the trie
      if (!current.children.containsKey(s)) {
 
        // Make wordCount 0 and
        // break out of loop
        wordCount = 0;
        break;
      }
 
      // Update the wordCount
      wordCount = current.num.get(s);
 
 
      // Go to next node
      current = current.children.get(s);
    }
 
    return wordCount;
  }
 
 
  // Driver Code
  public static void main(String[] args)
  {
    // input list of words
    Vector<String> words = new Vector<>();
    words.add("apk");
    words.add("app");
    words.add("apple");
    words.add("arp");
    words.add("array");
 
    // Given prefix to find
    String prefix = "ap";
 
    // Print the number of words with
    // given prefix
    System.out.println(countWords(words, prefix));
  }
}
 
// This code is contributed by Aman Kumar.




# Python3 implementation of counting the
# number of words in a trie with a
# given prefix
  
# Trie Node
class TrieNode:
     
    def __init__(self):
         
        # Using map to store the pointers
        # of children nodes for dynamic
        # implementation, for making the
        # program space efficient
        self.children = dict()
     
        # If isEndOfWord is true, then
        # node represents end of word
        self.isEndOfWord = False
     
        # num represents number of times
        # a character has appeared during
        # insertion of the words in the
        # trie
        self.num = dict()
 
# Declare root node
root = None
 
# Function to create New Trie Node
def getNewTrieNode():
     
    pNode = TrieNode()
    return pNode
  
# Function to insert a string in trie
def insertWord(word):
     
    global root
     
    # To hold the value of root
    current = root
  
    # To hold letters of the word
    s = ''
  
    # Traverse through strings in list
    for i in range(len(word)):
        s = word[i]
  
        # If s is not present in the
        # character field of current node
        if (s not in current.children):
  
            # Get new node
            p = getNewTrieNode()
             
            # Insert s in character
            # field of current node
            # with reference to node p
            current.children[s] = p
  
            # Insert s in num field
            # of current node with
            # value 1
            current.num[s] = 1
        else:
  
            # Increment the count
            # corresponding to the
            # character s
            current.num[s] = current.num[s] + 1
  
        # Go to next node
        current = current.children[s]
     
    current.isEndOfWord = True
 
# Function to count the number of
# words in trie with given prefix
def countWords(words, prefix):
     
    global root
    root = getNewTrieNode()
  
    # Size of list of string
    n = len(words)
  
    # Construct trie containing
    # all the words
    for i in range(n):
        insertWord(words[i])
         
    current = root
    s = ''
  
    # Initialize the wordCount = 0
    wordCount = 0
     
    for i in range(len(prefix)):
        s = prefix[i]
  
        # If the complete prefix is
        # not present in the trie
        if (s not in current.children):
  
            # Make wordCount 0 and
            # break out of loop
            wordCount = 0
            break
         
        # Update the wordCount
        wordCount = (current.num)[s]
  
        # Go to next node
        current = (current.children)[s]
  
    return wordCount
 
# Driver Code
if __name__=='__main__':
     
    # input list of words
    words = [ "apk", "app", "apple",
              "arp", "array" ]
  
    # Given prefix to find
    prefix = "ap"
  
    # Print the number of words with
    # given prefix
    print(countWords(words, prefix))
     
# This code is contributed by rutvik_56




using System;
using System.Collections.Generic;
 
// Define the TrieNode class to represent a node in the Trie data structure.
public class TrieNode
{
    public Dictionary<char, TrieNode> Children; // Dictionary to store child nodes.
    public bool IsEndOfWord; // Indicates whether this node represents the end of a word.
    public Dictionary<char, int> Num; // Dictionary to store the count of words that start with a particular character.
 
    // Constructor to initialize the TrieNode object.
    public TrieNode()
    {
        Children = new Dictionary<char, TrieNode>();
        IsEndOfWord = false;
        Num = new Dictionary<char, int>();
    }
}
 
// Define the Trie class to represent the Trie data structure.
public class Trie
{
    public TrieNode Root; // The root node of the Trie.
 
    // Constructor to initialize the Trie object.
    public Trie()
    {
        Root = new TrieNode();
    }
 
    // Method to insert a word into the Trie.
    public void InsertWord(string word)
    {
        TrieNode current = Root;
 
        foreach (char c in word)
        {
            if (!current.Children.ContainsKey(c)) // If the character is not present in the child nodes, add it.
            {
                current.Children = new TrieNode();
                current.Num = 1; // Since this is the first occurrence of the character, set its count to 1.
            }
            else // If the character is already present in the child nodes, increment its count.
            {
                current.Num++;
            }
            current = current.Children; // Move to the next node.
        }
 
        current.IsEndOfWord = true; // Set the IsEndOfWord flag to true for the last node in the word.
    }
 
    // Method to count the number of words in the Trie that start with a given prefix.
    public int CountWords(List<string> words, string prefix)
    {
        Trie trie = new Trie(); // Create a new Trie object.
        foreach (string word in words) // Insert all the words in the input list into the Trie.
        {
            trie.InsertWord(word);
        }
 
        TrieNode current = trie.Root; // Start at the root node of the Trie.
        int wordCount = 0;
 
        foreach (char c in prefix) // Traverse the Trie using the characters in the prefix.
        {
            if (!current.Children.ContainsKey(c)) // If the character is not present in the child nodes, there are no words in the Trie that start with the given prefix.
            {
                wordCount = 0;
                break;
            }
 
            wordCount = current.Num; // Get the count of words that start with the given prefix.
            current = current.Children; // Move to the next node.
        }
 
        return wordCount; // Return the count of words that start with the given prefix.
    }
}
 
// Define the Program class to test the Trie data structure.
public class Program
{
    public static void Main()
    {
        List<string> words = new List<string> { "apk", "app", "apple", "arp", "array" };
        string prefix = "ap";
        Trie trie = new Trie();
        int count = trie.CountWords(words, prefix); // Count the number of words that start with the given prefix.
        Console.WriteLine(count); // Print the count.
    }
}
// This code is contributed by rudra1807raj




// JavaScript implementation of counting the
// number of words in a trie with a
// given prefix
  
// Trie Node
class TrieNode {
    constructor() {
        // Using map to store the pointers
        // of children nodes for dynamic
        // implementation, for making the
        // program space efficient
        this.children = new Map();
     
        // If isEndOfWord is true, then
        // node represents end of word
        this.isEndOfWord = false;
     
        // num represents number of times
        // a character has appeared during
        // insertion of the words in the
        // trie
        this.num = new Map();
    }
}
 
// Declare root node
let root = null;
 
// Function to create New Trie Node
function getNewTrieNode() {
    let pNode = new TrieNode();
    return pNode;
}
  
// Function to insert a string in trie
function insertWord(word) {
    // To hold the value of root
    let current = root;
  
    // To hold letters of the word
    let s = '';
  
    // Traverse through strings in list
    for (let i = 0; i < word.length; i++) {
        s = word[i];
  
        // If s is not present in the
        // character field of current node
        if (!current.children.has(s)) {
            // Get new node
            let p = getNewTrieNode();
             
            // Insert s in character
            // field of current node
            // with reference to node p
            current.children.set(s, p);
  
            // Insert s in num field
            // of current node with
            // value 1
            current.num.set(s, 1);
        } else {
            // Increment the count
            // corresponding to the
            // character s
            current.num.set(s, current.num.get(s) + 1);
        }
  
        // Go to next node
        current = current.children.get(s);
    }
     
    current.isEndOfWord = true;
}
 
// Function to count the number of
// words in trie with given prefix
function countWords(words, prefix) {
    root = getNewTrieNode();
  
    // Size of list of string
    let n = words.length;
  
    // Construct trie containing
    // all the words
    for (let i = 0; i < n; i++) {
        insertWord(words[i]);
    }
     
    let current = root;
    let s = '';
  
    // Initialize the wordCount = 0
    let wordCount = 0;
     
    for (let i = 0; i < prefix.length; i++) {
        s = prefix[i];
  
        // If the complete prefix is
        // not present in the trie
        if (!current.children.has(s)) {
            // Make wordCount 0 and
            // break out of loop
            wordCount = 0;
            break;
        }
         
        // Update the wordCount
        wordCount = current.num.get(s);
  
        // Go to next node
        current = current.children.get(s);
    }
  
    return wordCount;
}
 
// Driver Code
let words = [ "apk", "app", "apple", "arp", "array" ];
let prefix = "ap";
console.log(countWords(words, prefix));  // Output: 3

Output
3

Time Complexity: O(n*l) where n = the number of words inserted in Trie and l = the length of the longest word inserted in Trie.

Auxiliary Space: O(n*l).
 


Article Tags :