#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#ifdef ENABLE_DEBUG
#define dump(a) cerr<<#a<<"="<<a<<endl
#define dumparr(a,n) cerr<<#a<<"["<<n<<"]="<<a[n]<<endl
#else
#define dump(a) 
#define dumparr(a,n) 
#endif
#define FOR(i, a, b) for(ll i = (ll)(a);i < (ll)(b);i++)
#define For(i, a) FOR(i, 0, a)
#define REV(i, a, b) for(ll i = (ll)(b)-1;i >= (ll)(a);i--)
#define Rev(i, a) REV(i, 0, a)
#define REP(a) For(i, a)
#define SIGN(a) (a==0?0:(a>0?1:-1))

typedef long long int ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<ll, ll> pll;
typedef pair<ll,pll> ppll;
typedef vector<ll> vll;
typedef long double ld;
typedef pair<ld,ld> pdd;

const ll INF=(1LL<<50);
#if __cplusplus<201700L
ll gcd(ll a, ll b) {
  if(a < b) return gcd(b, a);
  ll r;
  while ((r=a%b)) {
    a = b;
    b = r;
  }
  return b;
}
#endif
template<class T>
bool chmax(T& a,const T& b){
  if(a<b){
    a=b;
    return true;
  }
  return false;
}
template<class T>
bool chmin(T& a,const T& b){
  if(a>b){
    a=b;
    return true;
  }
  return false;
}
template<class S,class T>
std::ostream& operator<<(std::ostream& os,pair<S,T> a){
  os << "(" << a.first << "," << a.second << ")";
  return os;
}
template<class T>
std::ostream& operator<<(std::ostream& os,vector<T> a){
  os << "[ ";
  REP(a.size()){
    os<< a[i] << " ";
  }
  os<< " ]";
  return os;
}
ll concat(string a,string b){
  if(a.size()<b.size()){
    swap(a,b);
  }
  REP(a.size()-b.size()+1){
    bool f=true;
    For(j,b.size()){
      if(b[j]=='?'||a[i+j]=='?'||a[i+j]==b[j]){
      
      }else{
        f=false;
        break;
      }
    }
    if(f){
      return a.size();
    }
  }
  FOR(i,a.size()-b.size(),a.size()){
    bool f=true;
    for (ll j = 0; j < (ll)b.size() && i+j < (ll)a.size(); j++)
    {
      if(b[j]=='?'||a[i+j]=='?'||a[i+j]==b[j]){
      }else{
        f=false;
        break;
      }
    }
    if(f){
      return i+b.size();
    }
  }
  For(j,b.size()){
    bool f=true;
    for (ll i = 0; i+j < (ll)b.size(); i++)
    {
      if(b[i+j]=='?'||a[i]=='?'||a[i]==b[i+j]){
      }else{
        f=false;
        break;
      }
    }
    if(f){
      return j+a.size();
    }
  }
  return a.size()+b.size();
}
const ll MAX_SIZE=50000;
vector<bool> ba(MAX_SIZE,true),bc(MAX_SIZE,true),ca(MAX_SIZE,true);
bool match(char a,char b){
  return (a=='?')||(b=='?')||a==b;
}
void solve(std::string a, std::string b, std::string c){
  For(i,a.size())For(j,b.size()){
    if(!match(a[i],b[j])){
      ba[i-j+25000]=false;
    }
  }
  For(i,a.size())For(k,c.size()){
    if(!match(a[i],c[k])){
      ca[i-k+25000]=false;
    }
  }
  For(j,b.size())For(k,c.size()){
    if(!match(b[j],c[k])){
      bc[k-j+25000]=false;
    }
  }
  const ll SUM_bc=(b.size()+c.size());
  ll ans=a.size()+b.size()+c.size();
  FOR(j,-SUM_bc,a.size()+c.size()+1)FOR(k,-SUM_bc,a.size()+b.size()+1){
    if(ba[j+25000]&&ca[k+25000]&&bc[j-k+25000]){
      ll l=min(0LL,min(j,k)),r=max((ll)a.size(),max(j+(ll)b.size(),k+(ll)c.size()));
      ans=min(ans,r-l);
    }
  }
  cout<<ans<<endl;
}

int main(){
  cout<<setprecision(1000);
    std::string a;
    std::cin >> a;
    std::string b;
    std::cin >> b;
    std::string c;
    std::cin >> c;
    solve(a, b, c);
    return 0;
}


Measured memory_bytes: 256