Problem:
Score : 500 points

Problem Statement

Snuke has a string s.
From this string, Anuke, Bnuke, and Cnuke obtained strings a, b, and c, respectively, as follows:

Choose a non-empty (contiguous) substring of s (possibly s itself). Then, replace some characters (possibly all or none) in it with ?s.

For example, if s is mississippi, we can choose the substring ssissip and replace its 1-st and 3-rd characters with ? to obtain ?s?ssip.

You are given the strings a, b, and c.
Find the minimum possible length of s.

Constraints

1 \leq |a|, |b|, |c| \leq 2000

a, b, and c consists of lowercase English letters and ?s.

Input

Input is given from Standard Input in the following format:

a
b
c

Output

Print the minimum possible length of s.

Sample Input 1

a?c
der
cod

Sample Output 1

7

For example, s could be atcoder.

Sample Input 2

atcoder
atcoder
???????

Sample Output 2

7

a, b, and c may not be distinct.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
 
using namespace std;
 
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(a) a.begin(), a.end()
#define debug(x) cerr << #x << ": " << x << endl
 
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
 
template <typename T1, typename T2> bool chkmin(T1 &x, T2 y) { return y < x ? (x = y, true) : false; }
template <typename T1, typename T2> bool chkmax(T1 &x, T2 y) { return y > x ? (x = y, true) : false; }

bool good(char c1, char c2) {
  return c1 == c2 || c1 == '?' || c2 == '?';
}

const int maxN = 6003;
bool can[3][3][maxN];

signed main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
#ifdef DEBUG
  freopen("in", "r", stdin);
#endif

  vector<string> s(3, "");
  for (int i = 0; i < 3; ++i) {
    cin >> s[i];
  }
  vector<int> ord(3);
  iota(all(ord), 0);
  int ans = s[0].size() + s[1].size() + s[2].size();
  do {
    for (int p = 0; p < 3; ++p) {
      for (int q = p + 1; q < 3; ++q) {
        fill(can[p][q], can[p][q] + maxN, 1);
        for (int i = 0; i < s[ord[p]].size(); ++i) {
          bool &ok = can[p][q][i];
          for (int u = 0; u < s[ord[q]].size() && i + u < s[ord[p]].size(); ++u) {
            ok &= good(s[ord[q]][u], s[ord[p]][i + u]);
          }
        }
      }
    }
    for (int i = 0; i <= s[ord[0]].size(); ++i) {
      for (int j = i; j <= i + s[ord[1]].size() || j <= s[ord[0]].size(); ++j) {
        if (can[0][1][i] && can[0][2][j] && can[1][2][j - i]) {
          chkmin(ans, max(s[ord[0]].size(), max(i + s[ord[1]].size(), j + s[ord[2]].size())));
        }
      }
    }
  } while (next_permutation(all(ord)));
  cout << ans << '\n';

  return 0;
}