#pragma target("avx")
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> P;
typedef vector<ll> V;
typedef unordered_map<ll, ll> U_MAP;
typedef priority_queue<ll> pq;
typedef priority_queue<ll, vector<ll>, greater<ll>> rpq;
constexpr ll INF = 1e9, MOD = 1e9 + 7, ohara = 1e6 + 10;
constexpr ll LINF = 1e18;

#define rep(i, n) for (ll(i) = 0; (i) < (int)(n); (i)++)
#define rrep(i, a, b) for (ll i = (a); i < (b); i++)
#define rrrep(i, a, b) for (ll i = (a); i >= (b); i--)
#define all(v) (v).begin(), (v).end()
#define Size(n) (n).size()
#define Cout(x) cout << (x) << endl
#define doublecout(a) cout << fixed << setprecision(15) << a << endl;
#define fi first
#define se second
#define m_p make_pair
#define p_b push_back
string to_string(string s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string)s); }
string to_string(bool b) { return (b ? "true" : "false"); }
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto& x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)

//------ Believe yourself as a genius!!!!!! ------

int dy[] = {1, 0, -1, 0};
int dx[] = {0, 1, 0, -1};
// int dy[]={-1,0,1,-1,1,-1,0,1};int dx[]={-1,-1,-1,0,0,1,1,1};
string alph("abcdefghijklmnopqrstuvwxyz"), s[5], a, b, c;
ll n, cnt, ans, d, tmp, m, h, w, x, y, sum, k, q;

int main(void) {
  cin.tie(0);
  cout.tie(0);
  ios::sync_with_stdio(false);

  rep(i, 3) cin >> s[i];

  vector<ll> p(3);
  rep(i, 3) p[i] = i;
  ans = LINF;
  do {
    a = s[p[0]], b = s[p[1]], c = s[p[2]];
    bool valid1[2500] = {}, valid2[2500] = {}, valid3[2500] = {};
    rep(i, Size(a)) {
      int ok = 0;
      cnt = 0;
      rrep(j, i, min((ll)Size(a), i + (ll)Size(b))) {
        cnt++;
        if (a[j] == '?' || b[cnt - 1] == '?') continue;
        if (a[j] == b[cnt - 1]) continue;
        ok = 1;
      }
      if (!ok) valid1[i] = true;
    }

    rep(i, Size(b)) {
      int ok = 0;
      cnt = 0;
      rrep(j, i, min((ll)Size(b), i + (ll)Size(c))) {
        cnt++;
        if (b[j] == '?' || c[cnt - 1] == '?') continue;
        if (b[j] == c[cnt - 1]) continue;
        ok = 1;
      }
      if (!ok) valid2[i] = true;
    }

    rep(i, Size(a)) {
      int ok = 0;
      cnt = 0;
      rrep(j, i, min((ll)Size(a), i + (ll)Size(c))) {
        cnt++;
        if (a[j] == '?' || c[cnt - 1] == '?') continue;
        if (a[j] == c[cnt - 1]) continue;
        ok = 1;
      }
      if (!ok) valid3[i] = true;
    }

    valid1[Size(a)] = true, valid2[Size(b)] = true, valid3[Size(a)] = true;
    rep(i, Size(a) + 1) {
      rep(j, Size(b) + 1) {
        if (!valid1[i] || !valid2[j]) continue;
        if (i + j <= Size(a) - 1) {
          if (!valid3[i + j]) continue;
        }
        ll len = Size(a);
        len = max(len, i + (ll)Size(b));
        len = max(len, i + j + (ll)Size(c));
        ans = min(ans, len);
      }
    }

    rep(i, Size(a) + 1) {
      rrep(j, i + 1, Size(a) + 1) {
        if (i + Size(b) - 1 >= j) continue;
        if (!valid1[i] || !valid3[j]) continue;
        ll len = Size(a);
        len = max(len, j + (ll)Size(c));
        ans = min(ans, len);
      }
    }
  } while (next_permutation(all(p)));

  Cout(ans);

  return 0;
}


Measured memory_bytes: 256