### BUGGY CODE ###

#!/usr/bin/env python3
import sys

def getNextMin(a,b,bi,c):
    l = max(len(a)+1,bi+len(b)+1)
    for i in range(bi,l):
        match = True
        for j in range(len(c)):
            if c[j] == '?':
                continue
            if i+j < len(a) and a[i+j] != '?' and a[i+j] != c[j]:
                match = False
                break
            if i-bi+j < len(b) and b[i-bi+j] != '?' and b[i-bi+j] != c[j]:
                match = False
                break
        if match:
            return max(len(a),len(b)+bi,len(c)+i)
        # if match:
        #     substr = ""
        #     for k in range(bi):
        #         substr+=" "
        #     substr2 = ""
        #     for j in range(i):
        #         substr2+=" "
        #     r = max(len(a),len(b)+bi,len(c)+i)
        #     print(f"___MATCH___{bi}-{i}---->{r}")
        #     print(''.join(a))
        #     print(substr + ''.join(b))
        #     print(substr2 + ''.join(c))
        #     break
    

def getMin(a,b,c):
    m = 10**16
    for i in range(len(a)+1):
        match = True
        bi = i
        for j in range(len(b)):
            if i+j >=len(a):
                break
            if a[i+j] != '?' and b[j] != '?' and a[i+j] != b[j]:
                match = False
                break
        if match:
            m=min(m,getNextMin(a,b,bi,c))
    return m
            


def solve(a: str, b: str, c: str):
    a = list(a)
    b = list(b)
    c = list(c)
    print(min(getMin(a,b,c),getMin(a,c,b),getMin(b,c,a),getMin(b,a,c),getMin(c,a,b),getMin(c,b,a)))
    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    a = next(tokens)  # type: str
    b = next(tokens)  # type: str
    c = next(tokens)  # type: str
    solve(a, b, c)

if __name__ == '__main__':
    main()


### FIXED CODE ###

import sys

def match(a,b):
    return a == '?' or b== '?' or a == b


def solve(a, b, c):
    a = list(a)
    b = list(b)
    c = list(c)
    ab = [False] * 100000
    ac = [False] * 100000
    bc = [False] * 100000
    for i in range(len(a)):
        for j in range(len(b)):
            if not match(a[i],b[j]):
                ab[i-j+50000] = True
    for i in range(len(b)):
        for j in range(len(c)):
            if not match(b[i],c[j]):
                bc[i-j+50000] = True
    for i in range(len(a)):
        for j in range(len(c)):
            if not match(a[i],c[j]):
                ac[i-j+50000] = True
    M = max(len(a),len(b),len(c))
    ans = M*3
    for i in range(-M*2,M*2+1):
        for j in range(-M*2,M*2+1):
            if not ab[i + 50000] and not ac[j + 50000] and not bc[j-i + 50000]:
                L = min(i,j,0)
                R = max(len(a),len(b)+i,len(c)+j)
                ans = min(ans,R-L)
    print(ans)
    return


# Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    a = next(tokens)  # type: str
    b = next(tokens)  # type: str
    c = next(tokens)  # type: str
    solve(a, b, c)

if __name__ == '__main__':
    main()