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: Wrong Answer)

#include <iostream>
#include <string>
#include <vector>
#include <algorithm> // sort
#include <map> // pair
#include <queue>
#include<iomanip>
#include <cmath>
#include <set>
#include <unordered_set>

#define ABS(x) ((x)>0?(x):-(x))
#define MIN(x,y) ((x)>(y)?(y):(x))
#define MAX(x,y) ((x)<(y)?(y):(x))

#define SIZE_OF_ARRAY(array) (sizeof(array)/sizeof(array[0]))

#define INF 1000000000

using namespace std;
typedef long long ll;

ll newton(long long int a, long long int  b)
{
	if(a==b)
		return a;
	while(a != 0 && b != 0)
	{
		if(a > b)
		{
			b += a;
			a = b-a;
			b -= a;
		}
		b %= a;
	}
	return a;
}

struct UnionFind {
	vector<int> p;
	UnionFind(int N):p(N)
	{
		for(int i=0; i< N; i++)
		{
			p[i] = i;
		}
	}
	int root(int x)
	{
		if(p[x] == x)
			return x;
		return p[x] = root(p[x]);
	}
	void unite(int x, int y)
	{
		int rx = root(x);
		int ry = root(y);
		if(rx == ry) return;
		p[rx] = ry;
	}
	bool issame(int x, int y)
	{
		int rx = root(x);
		int ry = root(y);
		return rx == ry;
	}
};

//大きな数に対する割り算をするとき、MODを指定することで掛け算の値に変換できる

ll div2mul_calc(ll a, ll b, ll m)
{
	if (b == 0) {
        return 1;
    } else if (b % 2 == 0) {
        ll d = div2mul_calc(a, b / 2, m);
        return (d * d) % m;
    } else {
        return (a * div2mul_calc(a, b - 1, m)) % m;
    }
}
ll div2mul(ll n, ll mod)
{
	return div2mul_calc(n, mod-2, mod);
}

ll twoRow(ll a, ll b, ll mod)
{
	ll ret = 1;
	for(ll i = 1 ;i <= a+b;++i)
	{
		ret *= i;
		ret %= mod;
	}
	for(ll i = 1 ;i <= a;++i)
	{
		ret *= div2mul(i,mod);
		ret %= mod;
	}
	for(ll i = 1 ;i <= b;++i)
	{
		ret *= div2mul(i,mod);
		ret %= mod;
	}
	return ret;
}

struct edge {
    int from; //出発点
    int to;   //到達点
    int cost; //移動コスト
};

vector< ll > divisor(ll n) {
  vector< ll > ret;
  for(ll i = 1; i * i <= n; i++) {
    if(n % i == 0) {
      ret.push_back(i);
      if(i * i != n) ret.push_back(n / i);
    }
  }
  sort(ret.begin(), ret.end());
  return (ret);
}
/*
小数の桁数を指定する
	cout << setprecision(8)<< mp[0]-mx << endl;
*/
ll nx[2000000] = {0};
ll cur[2000000] = {0};

string concat(string l, string r, int n) {
	int ll=l.size();
	int rl=r.size();
	string ret = ""+l;
	for(int i=n;i<ll&&i-n<rl;++i)
	{
		if(ret[i]=='?' && r[i-n]!='?')
		{
			ret[i] = r[i-n];
		}
	}
	if(n+rl > ll)
		ret += r.substr(ll-n);
	return ret;
}


int main()
{
	int ans = 100000;
	int N,T=1, M;
	string s[3];
	cin >> s[0] >> s[1] >> s[2];

	if(s[2].size() > s[1].size()){
		int i = s[1].size();
		s[1]+=s[2];
		s[2]=s[1].substr(0, i);
		s[1]=s[1].substr(i);
	}
	if(s[1].size() > s[0].size()){
		int i = s[0].size();
		s[0]+=s[1];
		s[1]=s[0].substr(0, i);
		s[0]=s[0].substr(i);
	}
	if(s[2].size() > s[1].size()){
		int i = s[1].size();
		s[1]+=s[2];
		s[2]=s[1].substr(0, i);
		s[1]=s[1].substr(i);
	}
	string S;
	int i,j,k;
	int s0=s[0].size();
	int s1=s[1].size();
	for(i=0;i<s0;++i)
	{
		k = MIN(s1,s0-i);
		for(j=0;j<k;++j)
		{
			if(s[0][i+j]!=s[1][j]&&s[0][i+j]!='?'&&s[1][j]!='?'){
				break;
			}
		}
		if(j==k) {
			break;
		}
	}
	S = concat(s[0],s[1],i);
	s0 = S.size();
	s1 = s[2].size();
	for(i=0;i<s0;++i)
	{
		k = MIN(s1,s0-i);
		for(j=0;j<k;++j)
		{
			if(S[i+j]!=s[2][j]&&S[i+j]!='?'&&s[2][j]!='?'){
				break;
			}
		}
		if(j==k) {
			break;
		}
	}
	if(s0-i<s1)
		k = i + s1;
	else
		k = s0;
	if(k < ans)
		ans = k;

	for(i=0;i<s1;++i)
	{
		for(j=i;j<s1;++j)
		{
			if(S[j-i]!=s[2][j]&&S[j-i]!='?'&&s[2][j]!='?'){
				break;
			}
		}
		if(j==s1) {
			break;
		}
	}
	k = i + s0;
	if(k < ans)
		ans = k;




	s0=s[0].size();
	s1=s[1].size();
	for(i=0;i<s1;++i)
	{
		for(j=i;j<s1;++j)
		{
			if(s[0][j-i]!=s[1][j]&&s[0][j-i]!='?'&&s[1][j]!='?'){
				break;
			}
		}
		if(j==s1) {
			break;
		}
	}
	S = concat(s[1],s[0],i);
	s0 = S.size();
	s1 = s[2].size();
	for(i=0;i<s0;++i)
	{
		k = MIN(s1,s0-i);
		for(j=0;j<k;++j)
		{
			if(S[i+j]!=s[2][j]&&S[i+j]!='?'&&s[2][j]!='?'){
				break;
			}
		}
		if(j==k) {
			break;
		}
	}
	if(s0-i<s1)
		k = i + s1;
	else
		k = s0;
	if(k < ans)
		ans = k;

	for(i=0;i<s1;++i)
	{
		for(j=i;j<s1;++j)
		{
			if(S[j-i]!=s[2][j]&&S[j-i]!='?'&&s[2][j]!='?'){
				break;
			}
		}
		if(j==s1) {
			break;
		}
	}
	k = i + s0;
	if(k < ans)
		ans = k;




	s0=s[0].size();
	s1=s[2].size();
	for(i=0;i<s0;++i)
	{
		k = MIN(s1,s0-i);
		for(j=0;j<k;++j)
		{
			if(s[0][i+j]!=s[2][j]&&s[0][i+j]!='?'&&s[2][j]!='?'){
				break;
			}
		}
		if(j==k) {
			break;
		}
	}
	S = concat(s[0],s[2],i);
	s0 = S.size();
	s1 = s[1].size();
	for(i=0;i<s0;++i)
	{
		k = MIN(s1,s0-i);
		for(j=0;j<k;++j)
		{
			if(S[i+j]!=s[1][j]&&S[i+j]!='?'&&s[1][j]!='?'){
				break;
			}
		}
		if(j==k) {
			break;
		}
	}
	if(s0-i<s1)
		k = i + s1;
	else
		k = s0;
	if(k < ans)
		ans = k;

	for(i=0;i<s1;++i)
	{
		for(j=i;j<s1;++j)
		{
			if(S[j-i]!=s[1][j]&&S[j-i]!='?'&&s[1][j]!='?'){
				break;
			}
		}
		if(j==s1) {
			break;
		}
	}
	k = i + s0;
	if(k < ans)
		ans = k;




	s0=s[0].size();
	s1=s[2].size();
	for(i=0;i<s1;++i)
	{
		for(j=i;j<s1;++j)
		{
			if(s[0][j-i]!=s[2][j]&&s[0][j-i]!='?'&&s[2][j]!='?'){
				break;
			}
		}
		if(j==s1) {
			break;
		}
	}
	S = concat(s[2],s[0],i);
	s0 = S.size();
	s1 = s[1].size();
	for(i=0;i<s0;++i)
	{
		k = MIN(s1,s0-i);
		for(j=0;j<k;++j)
		{
			if(S[i+j]!=s[1][j]&&S[i+j]!='?'&&s[1][j]!='?'){
				break;
			}
		}
		if(j==k) {
			break;
		}
	}
	if(s0-i<s1)
		k = i + s1;
	else
		k = s0;
	if(k < ans)
		ans = k;

	for(i=0;i<s1;++i)
	{
		for(j=i;j<s1;++j)
		{
			if(S[j-i]!=s[1][j]&&S[j-i]!='?'&&s[1][j]!='?'){
				break;
			}
		}
		if(j==s1) {
			break;
		}
	}
	k = i + s0;
	if(k < ans)
		ans = k;
	cout << ans << endl;
	return 0;
}