title: Check If a Word Occurs As a Prefix of Any Word in a Sentence
slug: check-if-word-occurs-as-prefix
difficulty: easy
leetcode_id: 1455
leetcode_url: https://leetcode.com/problems/check-if-a-word-occurs-as-a-prefix-of-any-word-in-a-sentence/
categories:
  - strings
patterns:
  - slug: two-pointers
    is_optimal: true

function_signature: "def is_prefix_of_word(sentence: str, search_word: str) -> int:"

test_cases:
  visible:
    - input: { sentence: "i love eating burger", search_word: "burg" }
      expected: 4
    - input: { sentence: "this problem is an easy problem", search_word: "pro" }
      expected: 2
    - input: { sentence: "i am tired", search_word: "you" }
      expected: -1
  hidden:
    - input: { sentence: "hello", search_word: "hello" }
      expected: 1
    - input: { sentence: "hello world", search_word: "world" }
      expected: 2
    - input: { sentence: "a b c", search_word: "a" }
      expected: 1
    - input: { sentence: "abc def ghi", search_word: "xyz" }
      expected: -1
    - input: { sentence: "hellohello", search_word: "ell" }
      expected: -1

description: |
  Given a `sentence` that consists of some words separated by a **single space**, and a `searchWord`, check if `searchWord` is a prefix of any word in `sentence`.

  Return *the index of the word in* `sentence` *(**1-indexed**) where* `searchWord` *is a prefix of this word*. If `searchWord` is a prefix of more than one word, return the index of the first word **(minimum index)**. If there is no such word return `-1`.

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

constraints: |
  - `1 <= sentence.length <= 100`
  - `1 <= searchWord.length <= 10`
  - `sentence` consists of lowercase English letters and spaces.
  - `searchWord` consists of lowercase English letters.

examples:
  - input: 'sentence = "i love eating burger", searchWord = "burg"'
    output: "4"
    explanation: '"burg" is prefix of "burger" which is the 4th word in the sentence.'
  - input: 'sentence = "this problem is an easy problem", searchWord = "pro"'
    output: "2"
    explanation: '"pro" is prefix of "problem" which is the 2nd and the 6th word in the sentence, but we return 2 as it''s the minimal index.'
  - input: 'sentence = "i am tired", searchWord = "you"'
    output: "-1"
    explanation: '"you" is not a prefix of any word in the sentence.'

explanation:
  intuition: |
    Think of the sentence as a sequence of words laid out in a row, like books on a shelf. You're looking for the first book whose title *starts with* a specific set of letters.

    The key insight is that we don't need any fancy string matching algorithms here. The problem is straightforward: split the sentence into individual words, then check each word one by one to see if it begins with `searchWord`.

    Since we want the **first** matching word, we iterate through the words in order and return immediately when we find a match. This "early return" pattern is efficient because we stop as soon as we find what we're looking for.

    The prefix check itself is simple: a word has `searchWord` as a prefix if the first `len(searchWord)` characters of the word exactly match `searchWord`. Most languages provide a built-in `startswith()` or similar method for this.

  approach: |
    We solve this using a **Linear Scan with Prefix Check**:

    **Step 1: Split the sentence into words**

    - Use the space character as the delimiter to break the sentence into a list of words
    - This gives us direct access to each word by index

    &nbsp;

    **Step 2: Iterate through words with their indices**

    - For each word, check if it starts with `searchWord`
    - Python's `str.startswith()` method handles the prefix comparison efficiently
    - Remember the problem uses **1-indexed** positions, so we need to add 1 to the 0-based index

    &nbsp;

    **Step 3: Return the result**

    - If a word matches, return its 1-indexed position immediately
    - If no word matches after checking all, return `-1`

    &nbsp;

    This approach works because we process words in order, guaranteeing we find the minimum index first.

  common_pitfalls:
    - title: Off-by-One Error with 1-Indexing
      description: |
        The problem explicitly states that word positions are **1-indexed**, not 0-indexed. Many programming languages use 0-based indexing by default.

        If you iterate with a loop like `for i in range(len(words))` and return `i` directly, you'll be off by one. The first word should return `1`, not `0`.

        Always add 1 to convert from 0-indexed to 1-indexed, or use `enumerate(words, start=1)`.
      wrong_approach: "Returning 0-indexed position directly"
      correct_approach: "Add 1 to convert to 1-indexed position"

    - title: Manual Prefix Checking Errors
      description: |
        If you implement prefix checking manually instead of using built-in methods, you might forget to check if the word is long enough.

        For example, checking `word[:len(searchWord)] == searchWord` works, but manually comparing character-by-character without bounds checking could cause index out of range errors when the word is shorter than the search word.

        Using `startswith()` handles all edge cases automatically.
      wrong_approach: "Manual character comparison without length check"
      correct_approach: "Use built-in startswith() or slice with length validation"

    - title: Forgetting Empty String Edge Cases
      description: |
        While the constraints guarantee non-empty inputs, in a real interview you might encounter edge cases like empty sentences or empty search words.

        An empty `searchWord` is technically a prefix of every word. Be prepared to discuss how you'd handle these cases if the constraints were relaxed.

  key_takeaways:
    - "**Use built-in methods**: `startswith()` is cleaner and handles edge cases better than manual prefix checking"
    - "**Early return pattern**: Stop iterating as soon as you find the answer to avoid unnecessary work"
    - "**Watch for indexing conventions**: Problems often specify 1-indexed results when natural language is involved"
    - "**String splitting is your friend**: Converting a sentence to a word list simplifies iteration and access"

  time_complexity: "O(n * m). We iterate through each character of the sentence once during split (O(n)), then for each word we may compare up to `m` characters where `m` is the length of `searchWord`. In the worst case, we check all words."
  space_complexity: "O(n). We store the list of words after splitting, which in the worst case contains all characters from the original sentence."

solutions:
  - approach_name: Linear Scan with startswith()
    is_optimal: true
    code: |
      def is_prefix_of_word(sentence: str, search_word: str) -> int:
          # Split sentence into list of words
          words = sentence.split()

          # Check each word (enumerate with start=1 for 1-indexed result)
          for i, word in enumerate(words, start=1):
              # If this word starts with searchWord, return its position
              if word.startswith(search_word):
                  return i

          # No word had the prefix
          return -1
    explanation: |
      **Time Complexity:** O(n * m) — Where n is the sentence length and m is the search word length. Split is O(n), and each startswith check is O(m) in the worst case.

      **Space Complexity:** O(n) — The words list stores all characters from the sentence.

      This is the cleanest and most Pythonic solution. Using `enumerate` with `start=1` handles the 1-indexing requirement elegantly.

  - approach_name: Manual Iteration Without Split
    is_optimal: false
    code: |
      def is_prefix_of_word(sentence: str, search_word: str) -> int:
          word_index = 1  # 1-indexed word counter
          word_start = 0  # Start position of current word

          i = 0
          while i <= len(sentence):
              # End of word: either space or end of sentence
              if i == len(sentence) or sentence[i] == ' ':
                  # Extract current word
                  word = sentence[word_start:i]

                  # Check if searchWord is a prefix
                  if word.startswith(search_word):
                      return word_index

                  # Move to next word
                  word_index += 1
                  word_start = i + 1

              i += 1

          return -1
    explanation: |
      **Time Complexity:** O(n * m) — Same as the split approach.

      **Space Complexity:** O(w) — Where w is the length of the longest word (for the substring extraction).

      This approach avoids creating a list of all words upfront, potentially saving memory for very long sentences. However, it's more complex and the savings are negligible given the problem constraints.
