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 <iostream>
#include <fstream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cstring>
#include <cassert>
#include <utility>
#include <iomanip>
#include <chrono>
#include <random>
#include <bitset>

using namespace std;

#define sz(x) (int) x.size()
#define unique(x) x.erase(unique(x.begin(), x.end()), x.end())
#define all(a) a.begin(), a.end()
#define sqr(x) ((x) * (x)) 
#define y1 aksjdaskdjksjfksdjf
#define left kdnvldvoiwejifejg
#define right lkdsjflksdjfdjfk
#define prev asdasfsadjkjsdfjs
#define tm aklsjdasjdasjdkdjjf
#define lcm hddalkwjeidjjhasda
#define random_shuffle asdasdd

const int MAXN = 2050;

bool eq(char a, char b) {
  if (a != '?' && b != '?' && a != b) {
    return false;
  }
  return true;
}

void calcCan(string a, string b, bool can[]) {
  for (int i = 0; i < sz(a); i++) {
    can[i] = true;
    for (int j = 0; j < sz(b); j++) {
      int cur = i + j;
      if (cur >= sz(a)) {
        break;
      }
      if (!eq(a[cur], b[j])) {
        can[i] = false;
        break;
      }
    }
  }
}

string s[5];
string a, b, c;
bool can1[MAXN], can2[MAXN], can3[MAXN];
int ans;

void solve() {
  calcCan(a, b, can1);
  calcCan(a, c, can2);
  calcCan(b, c, can3);

  int curAns = sz(a) + sz(b) + sz(c);
  int mnBc = sz(b) + sz(c);
  for (int i = 0; i < sz(b); i++) {
    if (can3[i]) {
      mnBc = max(sz(b), sz(c) + i);
      break;
    }
  }
  curAns = min(curAns, sz(a) + mnBc);

  // cerr << mnBc << endl;

  for (int i = 0; i < sz(a); i++) {
    if (!can1[i]) {
      continue;
    }
    if (i + sz(b) - 1 >= sz(a) - 1) {
      curAns = min(curAns, sz(b) + i + sz(c));
      for (int j = 0; j < sz(b); j++) {
        bool ok = can3[j];
        if (i + j < sz(a)) {
          ok &= can2[i + j];
        }
        if (ok) {
          curAns = min(curAns, i + max(sz(b), j + sz(c)));
        }
      }
      // curAns = min(curAns, i + mnBc);
    } else {
      curAns = min(curAns, sz(a) + sz(c));
      for (int j = i; j < sz(a); j++) {
        bool ok = can2[j];
        if (i + sz(b) - 1 >= j) {
          ok &= can3[j - i];
        }
        if (ok) {
          curAns = min(curAns, max(sz(a), j + sz(c)));
        }
      }
    }
  }

  // cerr << curAns << " " << a << " " << b << " " << c << endl;
  ans = min(ans, curAns);
}

int main() {

  getline(cin, s[0]);
  getline(cin, s[1]);
  getline(cin, s[2]);

  sort(s, s + 3);
  ans = sz(s[0]) + sz(s[1]) + sz(s[2]);

  do {
    a = s[0]; b = s[1]; c = s[2];
    solve();
  } while (next_permutation(s, s + 3));

  cout << ans << endl;

  return 0;
}