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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		
		String[] S = new String[]{A, B, C};
		int min = A.Length + B.Length + C.Length;
		
		HashSet<int>[][] L = new HashSet<int>[3][];
		for(int i=0;i<3;i++){
			L[i] = new HashSet<int>[3];
			for(int j=0;j<3;j++){
				L[i][j] = new HashSet<int>();
			}
		}
		
		for(int i=0;i<3;i++){
			for(int j=0;j<3;j++){
				if(i == j) continue;
				var s = S[i];
				var t = S[j];
				for(int k=-t.Length;k<=s.Length;k++){
					bool chk = true;
					for(int l=0;l<s.Length;l++){
						int ti = l - k;
						if(ti < 0 || ti >= t.Length) continue;
						if(s[l] == t[ti]) continue;
						if(s[l] == '?') continue;
						if(t[ti] == '?') continue;
						chk = false;
						break;
					}
					if(chk){
						L[i][j].Add(k);
					}
				}
				
			}
		}
		
		//for(int i=0;i<3;i++) for(int j=0;j<3;j++) Console.WriteLine("{0},{1}:{2}",i,j,String.Join(" ",L[i][j]));
		int[] a = new int[]{0,1,2};
		do {
			int i = a[0];
			int j = a[1];
			int k = a[2];
			foreach(var ij in L[i][j]){
				foreach(var ik in L[i][k]){
					int la = 0, ra = S[i].Length;
					int lb = ij, rb = ij + S[j].Length;
					int lc = ik, rc = ik + S[k].Length;
					if(lb <= lc && lc < rb){
						if(!L[j][k].Contains(lc - lb)) continue;
					}
					if(lc <= lb && lb < rc){
						if(!L[k][j].Contains(lb - lc)) continue;
					}
					int l = Math.Min(la, lb);
					l = Math.Min(l, lc);
					int r = Math.Max(ra, rb);
					r = Math.Max(r, rc);
					min = Math.Min(min, r - l);
				}
			}
			
		} while(NextPermutation(a));
		
		Console.WriteLine(min);
		
	}
	String A,B,C;
	public Sol(){
		A = rs();
		B = rs();
		C = rs();
	}
	
	static public bool NextPermutation<T>(T[] A)where T:IComparable<T>{
		for(int i=A.Length-2;i>=0;i--){
			if(A[i].CompareTo(A[i+1])<0){
				int trgt=Array.FindLastIndex(A,x=>A[i].CompareTo(x)<0);
				Swap(ref A[i],ref A[trgt]);
				Array.Reverse(A,i+1,A.Length-(i+1));
				return true;
			}
		}
		Array.Reverse(A);
		return false;
	}
	static void Swap<T>(ref T x, ref T y){
		T t=x;x=y;y=t;
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}