def levenshtein_1d_blocks(string, transpositions=False, flag='\x00'):
    """
    Function returning the minimal set of longest Levenshtein distance <= 1
    blocking keys of target string. Under the hood, this splits the given
    string into an average of 3 blocks (2 when string length is even, 4 when
    odd). When supporting transpositions, the function will always return
    4 blocks to handle the case when middle letters are transposed.

    Note that this method therefore yields a constant number of keys, as
    opposed to ngrams which yield a number of keys proportional to the size
    of the given strings.

    The intuition of this technique can be found in Knuth. Similar concepts can
    be found in Doster. This is also reminiscent of q-samples.

    This method works quite well because it's independent of the string's
    length and therefore implicitly incorporates the string's length into
    the generated keys.

    Indeed, this method minimizes the number of produced keys (the number
    is constant, contrary to n-grams, for instance) and minimizes the
    probability of two strings colliding.

    What's more, this method is exact and won't generate false negatives like
    n-grams would.

    Args:
        string (str): Target string.
        transpositions (bool, optional): Whether to support transpositions
            like with the Damerau-Levenshtein distance. Defaults to False.

    Returns:
        tuple: Resulting blocks.

    """
    n = len(string)

    if n == 1:
        return (flag + string, string + flag, flag)

    h = n // 2

    # String has even length, we just split in half
    if n % 2 == 0:

        first_half = flag + string[:h]
        second_half = string[h:] + flag

        # For transpositions, we swap once the middle characters
        if transpositions:

            first_transposed_half = flag + string[:h - 1] + second_half[0]
            second_transposed_half = first_half[-1] + string[h + 1:] + flag

            return (first_half, second_half, first_transposed_half, second_transposed_half)
        else:
            return (first_half, second_half)

    # String has odd length, we split twice
    h1 = h + 1

    first_half = flag + string[:h]
    second_half = string[h:] + flag
    first_half1 = flag + string[:h1]
    second_half1 = string[h1:] + flag

    return (first_half, second_half, first_half1, second_half1)