def find_index(text, pattern, start=0):
    """Return the starting index of the first occurrence of pattern in text,
    or None if not found.
    Runtime Complexity: θ(n) Space Complexity: θ(1)"""
    assert isinstance(text, str), 'text is not a string: {}'.format(text)
    assert isinstance(pattern, str), 'pattern is not a string: {}'.format(text)

    # we need two variables to keep track of what
    # index we are at in the pattern and how many
    # characters of pattern have been matched consecutively
    patternIndex = 0
    matchedCount = 0

    # loop through characters in text
    for textIndex in range(start, len(text)):

        # handle the special case of an empty string pattern
        if len(pattern) == 0:
            return textIndex

        # increment pattern count and index if current character
        # in pattern matches current character in text
        if text[textIndex] == pattern[patternIndex]:
            matchedCount += 1
            patternIndex += 1

        # if there is overlap, restart the pattern count and index at 1
        elif text[textIndex] == pattern[0]:
            patternIndex = 1
            matchedCount = 1

        # otherwise restart the pattern count and index at 0
        else:
            patternIndex = 0
            matchedCount = 0

        # once the pattern count becomes equal to length of pattern
        # we have a match - return the starting index
        if matchedCount >= len(pattern):
            return textIndex - matchedCount+1

    # return None if index was not found
    return None