L2 · Working engineerStrings~8 min · 5 tests#25

Find All Occurrences of a Substring

Return every start index where a substring occurs in a string, overlaps included, using str.find in a loop. Covers the O(n·m) cost and KMP follow-up.

The problem

Return a list of every index where sub starts inside s. Overlapping matches count: in "aaaa" the substring "aa" starts at 0, 1, 2.

Assume sub is non-empty.

Examples

  1. Example 1

    Input

    find_all('abababab', 'ab')

    Expected output

    [0, 2, 4, 6]
  2. Example 2

    Input

    find_all('aaaa', 'aa')

    Expected output

    [0, 1, 2]

+ 3 hidden tests on Submit — sub longer than s.

Edge cases to ask about

  • No match
  • Overlapping matches
  • sub longer than s

Hints

0/3

    How an interviewer scores this

    0/9
    Python 3.13 · find_all
    ⌘/Ctrl + Enter runs the examples

    Your code runs in real CPython inside your browser — nothing is sent anywhere. The first run downloads the interpreter (about 6 MB, once). Your code is saved on this device as you type.

    Complexity Lab

    What does this cost as n grows?

    Interviewers score the analysis as much as the code. Commit to an answer first — then check it, and measure your code against the optimal one at growing input sizes.

    Time complexity of the optimal solution
    Space complexity (extra memory)

    Pick both to reveal the answer.

    Measure it

    Runs the function on inputs of size 250 up to 16,000 and records the time and peak memory. Slow solutions stop early — a short curve is itself the answer.

    From brute force to optimal

    The progression an interviewer wants to hear, one step at a time.

    ApproachTimeSpaceIdea
    Compare a slice at every indexO(n·m)O(m)Each slice is a copy of length m.
    str.find from i + 1O(n·m) worstO(1)find is implemented in C and skips fast; restarting at i + 1 keeps overlaps.
    bestKMPO(n + m)O(m)Prefix table means no character is re-compared.
    Walkthrough of the optimal approach (try it yourself first)

    Loop on s.find(sub, i + 1) until it returns -1. Restarting at i + 1 (not i + len(sub)) is what makes overlapping matches count.

    The theoretical answer is O(n·m) worst case. If the interviewer pushes, describe KMP: a prefix-function table lets you avoid re-comparing characters, giving O(n + m).

    Complexity: O(n·m) time, O(1) space. In the worst case each of the n start positions compares up to m characters. KMP brings this to O(n + m).

    Reveal the reference solution
    def find_all(s, sub):
        out = []
        i = s.find(sub)
        while i != -1:
            out.append(i)
            i = s.find(sub, i + 1)
        return out

    The brute force, for comparison

    def find_all(s, sub):
        m = len(sub)
        return [i for i in range(len(s) - m + 1) if s[i:i + m] == sub]

    Follow-ups interviewers ask

    • Non-overlapping matches only.
    • Implement KMP.

    Frequently asked interview questions

    Core interview concepts, complexities, and follow-ups scored by hiring teams.

    What is the time complexity of Find All Occurrences of a Substring in Python?

    The optimal solution runs in O(n·m) time and O(1) auxiliary space. In the worst case each of the n start positions compares up to m characters. KMP brings this to O(n + m).

    What is the brute-force approach, and how do you optimise it?

    Compare a slice at every index: O(n·m) time, O(m) space. Each slice is a copy of length m. str.find from i + 1: O(n·m) worst time, O(1) space. find is implemented in C and skips fast; restarting at i + 1 keeps overlaps. KMP: O(n + m) time, O(m) space. Prefix table means no character is re-compared.

    What follow-up questions do interviewers ask about Find All Occurrences of a Substring?

    Non-overlapping matches only. Implement KMP.