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.Generic;
using System.Linq;
using System.Text;

public class Solution
{
    static bool IsMatch(char c1, char c2)
    {
        return c1 == '?' || c2 == '?' || c1 == c2;
    }

    public static void Main()
    {
        var a = Console.ReadLine();
        var b = Console.ReadLine();
        var c = Console.ReadLine();

        const int Margin = 4000;
        const int Max = Margin * 2 + 1;
        var ab = Enumerable.Repeat(true, Max).ToArray();
        var ac = Enumerable.Repeat(true, Max).ToArray();
        var bc = Enumerable.Repeat(true, Max).ToArray();
        for (int i = 0; i < a.Length; i++)
        {
            for (int j = 0; j < b.Length; j++)
            {
                ab[i - j + Margin] &= IsMatch(a[i], b[j]);
            }
        }
        for (int i = 0; i < a.Length; i++)
        {
            for (int j = 0; j < c.Length; j++)
            {
                ac[i - j + Margin] &= IsMatch(a[i], c[j]);
            }
        }
        for (int i = 0; i < b.Length; i++)
        {
            for (int j = 0; j < c.Length; j++)
            {
                bc[i - j + Margin] &= IsMatch(b[i], c[j]);
            }
        }

        var min = int.MaxValue;
        for (int i = -Margin; i <= Margin; i++)
        {
            for (int j = -Margin; j <= Margin; j++)
            {
                var bcIndex = j - i + Margin;
                if (ab[i + Margin] && ac[j + Margin] && (bcIndex < 0 || bcIndex >= Max || bc[j - i + Margin]))
                {
                    var left = Math.Max(0, Math.Max(-i, -j));
                    var right = Math.Max(a.Length, Math.Max(b.Length + i, c.Length + j));
                    var len = left + right;
                    min = Math.Min(min, len);
                }
            }
        }

        Console.WriteLine(min);
    }
}