Given a haystack string and a needle string, return the index of the first occurrence of the needle, or −1 if it is absent. This is the classic substring-search primitive — the machine must slide the needle across the haystack and compare character by character.
The key insight: the search window only needs to start where the needle could still fit. If the needle has length m, the last viable start is len(haystack) - m — past that, the needle is longer than the remaining text and cannot match, so the machine stops early. Each start position is a fresh comparison from the needle's first character.
Approach:
- Guard: an empty needle returns 0 by definition.
- For each start from 0 to
len(haystack) - len(needle), compare the window. - Return the first matching start; else −1.
def str_str(haystack, needle):
n, m = len(haystack), len(needle)
if m == 0:
return 0
for start in range(n - m + 1):
if haystack[start:start + m] == needle:
return start
return -1Time: O(n·m) worst case. Space: O(1).
Trickiest edge case: needle longer than haystack — range(n - m + 1) is empty and the machine returns −1, which is correct but only because of the bounds guard; without it, the slice comparison would silently fail.