#include <bits/stdc++.h>

using namespace std;

/// Errichto debugger
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

const int N = 2020;

int Len[3][3][N];
bool Could[3][3][N];

bool Can(string s, string t, int i)
{
    for(int j = 0; j < t.size() && i + j < s.size(); j++)
        if(t[j] != '?' && s[i + j] != '?' && t[j] != s[i + j])
            return false;

    return true;
}

int Merge(string s, string t, int i)
{
    return max(s.size(), i + t.size());

    /*string Res;

    int j;
    for(j = 0; j < i; j++)  Res += s[j];

    for(; j - i < t.size() && j < s.size(); j++)
    {
        Res += "?";
        if(s[j] != '?')     Res.back() = s[j];
        if(t[j - i] != '?') Res.back() = t[j - i];
    }

    for(; j < s.size(); j++)        Res += s[j];
    for(; j - i < t.size(); j++)    Res += t[j - i];

    return Res.size();*/
}

int main()
{
    vector <string> a(3);
    for(int i = 0; i < 3; i++)  cin >> a[i];
    sort(a.begin(), a.end());

    int Ans = a[0].size() + a[1].size() + a[2].size();

    do
    {
        memset(Could, false, sizeof(Could));

        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                for(int k = 0; k <= a[0].size(); k++)
                    if(Can(a[i], a[j], k))
                        Could[i][j][k] = true, Len[i][j][k] = Merge(a[i], a[j], k);

        for(int i = 0; i <= a[0].size(); i++)
        {
            if(Could[0][1][i])
            {
                int x = Len[0][1][i];

                for(int j = i; j <= x; j++)
                {
                    if(Could[0][2][min((int) a[0].size(), j)])
                    {
                        if(Could[1][2][min((int) a[1].size(), j - i)])
                        {
                            int y = max(x, j + (int) a[2].size());

                            Ans = min(Ans, y);
                        }
                    }
                }
            }

            /*if(Can(a[0], a[1], i))
            {
                string s = Merge(a[0], a[1], i);

                for(int j = 0; j <= s.size(); j++)
                {
                    if(Can(s, a[2], j))
                    {
                        string t = Merge(s, a[2], j);

                        Ans = min(Ans, (int) t.size());
                    }
                }
            }*/
        }

    } while(next_permutation(a.begin(), a.end()));

    cout << Ans << endl;
}


Measured memory_bytes: 512