2185. Counting Words With a Given Prefix - Explanation

Problem Link

Description

You are given an array of strings words and a string pref.

Return the number of strings in words that contain pref as a prefix.

A prefix of a string s is any leading contiguous substring of s.

Example 1:

Input: words = ["pay","attention","practice","attend"], pref = "at"

Output: 2

Explanation: The two strings that contain "at" as a prefix are: "attention" and "attend".

Example 2:

Input: words = ["neetcode","neet","nee","code"], pref = "ne"

Output: 3

Explanation: The three strings that contain "ne" as a prefix are: "neetcode","neet" and "nee".

Constraints:

  • 1 <= words.length <= 100
  • 1 <= words[i].length, pref.length <= 100
  • words[i] and pref consist of lowercase English letters.


Topics

Company Tags

Please upgrade to NeetCode Pro to view company tags.



Prerequisites

Before attempting this problem, you should be comfortable with:

  • String Manipulation - Comparing characters and understanding prefix matching operations
  • Trie (Prefix Tree) - A tree-based data structure for efficient prefix storage and lookup
  • Array/List Traversal - Iterating through collections of strings

1. Brute Force

Intuition

To check if a word has a given prefix, we compare the first few characters of the word with the prefix string. If the word is shorter than the prefix, it cannot have that prefix. Otherwise, we check character by character until we either find a mismatch or confirm all prefix characters match.

Algorithm

  1. Initialize a counter to 0.
  2. For each word in the array:
    • Skip if the word is shorter than the prefix length.
    • Compare each character of the word with the corresponding character of the prefix.
    • If all characters match, increment the counter.
  3. Return the final count.
class Solution:
    def prefixCount(self, words: List[str], pref: str) -> int:
        N, res = len(pref), 0

        for w in words:
            if len(w) < len(pref):
                continue
            inc = 1
            for i in range(N):
                if w[i] != pref[i]:
                    inc = 0
                    break
            res += inc

        return res

Time & Space Complexity

  • Time complexity: O(mn)O(m * n)
  • Space complexity: O(1)O(1)

Where mm is the number of words and nn is the length of the string prefpref.


2. Built-In Method

Intuition

Most programming languages provide built-in methods to check if a string starts with a given prefix. These methods handle the character comparison internally and are optimized for the task, making the code cleaner and less error-prone.

Algorithm

  1. Initialize a counter to 0.
  2. For each word in the array, use the language's built-in prefix checking method (like startsWith or hasPrefix).
  3. If the word starts with the prefix, increment the counter.
  4. Return the final count.
class Solution:
    def prefixCount(self, words: List[str], pref: str) -> int:
        res = 0
        for w in words:
            res += w.startswith(pref)
        return res

Time & Space Complexity

  • Time complexity: O(mn)O(m * n)
  • Space complexity: O(1)O(1)

Where mm is the number of words and nn is the length of the string prefpref.


3. Trie

Intuition

A Trie (prefix tree) is a tree structure where each node represents a character. By inserting only the first few characters of each word (up to the prefix length), we build a compact structure. Each node keeps a count of how many words pass through it. After inserting all words, we traverse the trie following the prefix characters and return the count at the final node.

Algorithm

  1. Create a Trie data structure where each node has children and a count.
  2. For each word in the array:
    • If the word is at least as long as the prefix, insert the first prefix.length characters into the trie.
    • Increment the count at each node during insertion.
  3. Traverse the trie following the prefix characters.
  4. If any character is missing, return 0.
  5. Otherwise, return the count at the final node.
class PrefixNode:
    def __init__(self):
        self.children = {}   # a -> PrefixNode
        self.count = 0

class PrefixTree:
    def __init__(self):
        self.root = PrefixNode()

    def add(self, w: str, length: int) -> None:
        cur = self.root
        for i in range(length):
            if w[i] not in cur.children:
                cur.children[w[i]] = PrefixNode()
            cur = cur.children[w[i]]
            cur.count += 1

    def count(self, pref: str) -> int:
        cur = self.root
        for c in pref:
            if c not in cur.children:
                return 0
            cur = cur.children[c]
        return cur.count

class Solution:
    def prefixCount(self, words: List[str], pref: str) -> int:
        prefix_tree = PrefixTree()

        for w in words:
            if len(w) >= len(pref):
                prefix_tree.add(w, len(pref))

        return prefix_tree.count(pref)

Time & Space Complexity

  • Time complexity: O(ml+n)O(m * l + n)
  • Space complexity: O(ml)O(m * l)

Where mm is the number of words, nn is the length of the string prefpref and ll is the maximum length of a word.


Common Pitfalls

Checking Contains Instead of Starts With

The problem asks for words that start with the prefix, not words that contain the prefix anywhere. Using a contains/includes check instead of a starts-with check will incorrectly count words where the prefix appears in the middle.

# Wrong: Checks if prefix exists anywhere in the word
if pref in word:
    count += 1

# Correct: Checks if word starts with prefix
if word.startswith(pref):
    count += 1

Not Handling Words Shorter Than the Prefix

When manually comparing characters, forgetting to check if the word is at least as long as the prefix leads to index out of bounds errors or incorrect matches.

# Wrong: May cause index error if word is shorter than prefix
for i in range(len(pref)):
    if word[i] != pref[i]:  # Error when len(word) < len(pref)
        break

# Correct: Skip words shorter than the prefix
if len(word) < len(pref):
    continue
for i in range(len(pref)):
    if word[i] != pref[i]:
        break