def prefix_table(pattern):
    table = [0] * len(pattern)
    matched = 0
    for i in range(1, len(pattern)):
        while matched and pattern[i] != pattern[matched]:
            matched = table[matched - 1]
        if pattern[i] == pattern[matched]:
            matched += 1
        table[i] = matched
    return table


def find_all(text, pattern):
    if not pattern:
        return list(range(len(text) + 1))
    table = prefix_table(pattern)
    matched, positions = 0, []
    for i, char in enumerate(text):
        while matched and char != pattern[matched]:
            matched = table[matched - 1]
        if char == pattern[matched]:
            matched += 1
        if matched == len(pattern):
            positions.append(i - len(pattern) + 1)
            matched = table[matched - 1]
    return positions


if __name__ == '__main__':
    print(find_all('ababa', 'aba'))
