def z_preprocessing(S):
    """
    Z algorithm for the fundamental preprocessing of a string:
    Given a string S and a position i > 1, let Z_i(S) be the length of the longest
    substring of S that starts at i and matches a prefix of S.
    """
    n = len(S)
    z = [0] * n
    x, y = 0, 0
    for i in range(1, n):
        z[i] = max(0, min(z[i - x], y - i + 1))
        while i + z[i] < n and S[z[i]] == S[i + z[i]]:
            x = i
            y = i + z[i]
            z[i] += 1
    return z