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

using System;
using System.Linq;//リストの使用
using System.Collections.Generic;
using System.Text;//テキストの高速出力に必要
class Program
{
static string aa = Console.ReadLine();
static string bb = Console.ReadLine();
static string cc = Console.ReadLine();
static int aan = aa.Length;
static int bbn = bb.Length;
static int ccn = cc.Length;
static string a = "";
static string b = "";
static string c = "";
static int an = aa.Length;
static int bn = bb.Length;
static int cn = cc.Length;
static int answer = aan+bbn+ccn;
static int answerMinus = 0;//弾ける文字数の最大値
static int answerMinusMemo = 0;
static bool answerSkip = false;

	static void Main()
	{
    answerMinusMemo = Ans(0,1,2);
    answerMinus = Math.Max(answerMinus, answerMinusMemo);
    answerMinusMemo = 0;//ここまでaが真ん中、b,cが左右

    answerMinusMemo = Ans(0,2,1);
    answerMinus = Math.Max(answerMinus, answerMinusMemo);
    answerMinusMemo = 0;

    answerMinusMemo = Ans(1,0,2);
    answerMinus = Math.Max(answerMinus, answerMinusMemo);
    answerMinusMemo = 0;

    answerMinusMemo = Ans(1,2,0);
    answerMinus = Math.Max(answerMinus, answerMinusMemo);
    answerMinusMemo = 0;

    answerMinusMemo = Ans(2,0,1);
    answerMinus = Math.Max(answerMinus, answerMinusMemo);
    answerMinusMemo = 0;

    answerMinusMemo = Ans(2,1,0);
    answerMinus = Math.Max(answerMinus, answerMinusMemo);
    answerMinusMemo = 0;
    
		Console.WriteLine(answer-answerMinus);
	}

  static int Ans(int x, int y, int z)
  {
    if(x == 0) a=aa;
    if(x == 1) a=bb;
    if(x == 2) a=cc;
    if(x == 0) an=aan;
    if(x == 1) an=bbn;
    if(x == 2) an=ccn;
    if(y == 0) b=aa;
    if(y == 1) b=bb;
    if(y == 2) b=cc;
    if(y == 0) bn=aan;
    if(y == 1) bn=bbn;
    if(y == 2) bn=ccn;
    if(z == 0) c=aa;
    if(z == 1) c=bb;
    if(z == 2) c=cc;
    if(z == 0) cn=aan;
    if(z == 1) cn=bbn;
    if(z == 2) cn=ccn;

    if(bn <= an)
    {
      for(int i = 0; i < an; i++)
      {
        for(int j = 0; j < bn; j++)
        {
          if(i+j >= an) break;
          if(a[i+j] != b[j] && a[i+j] != '?' && b[j] != '?') break;
          if(j == bn-1) answerSkip = true;
        }
      }
    }
    if(answerSkip)
    {
      answerMinusMemo += bn;
      answerSkip = false;
    }
    else
    {
      for(int i = bn-1; i > 0; i--)
      {
        if(i > an) continue;

        for(int j = 0; j < i; j++)
        {
          if(a[j] != b[bn-i+j] && a[j] != '?' && b[bn-i+j] != '?') break;
        
          if(j == i-1)
          {
            answerMinusMemo += i;
            answerSkip = true;
          }
        }

        if(answerSkip) break;
      }
    }
    answerSkip = false;
    
    if(cn <= an)
    {
      for(int i = 0; i < an; i++)
      {
        for(int j = 0; j < cn; j++)
        {
          if(i+j >= an) break;
          if(a[i+j] != c[j] && a[i+j] != '?' && c[j] != '?') break;
          if(j == cn-1) answerSkip = true;
        }
      }
    }
    if(answerSkip)
    {
      answerMinusMemo += cn;
    }
    else
    {
      for(int i = cn-1; i > 0; i--)
      {
        if(i > an) continue;

        for(int j = 0; j < i; j++)
        {
          if(c[j] != a[an-i+j] && c[j] != '?' && a[an-i+j] != '?') break;
      
          if(j == i-1)
          {
            answerMinusMemo += i;
            answerSkip = true;
          }
        }

        if(answerSkip) break;
      }
    }
    answerSkip = false;
    return answerMinusMemo;
    
  }
  
}