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 Kotlin (1.0.0) (judge verdict: Accepted)

fun main(args: Array<String>) {
    val s0 = Array<String>(3) { next() }.sorted()
    val s = Array<String>(3) { s0[it] }
    val MX = 2001
    var ans = MX * 3
    val d = Array(3) { Array(3) { BooleanArray(MX) } }
    do {
        for (i in 0 until 3) for (j in 0 until 3) for (k in 0 until s[i].length) {
            if (i >= j) continue
            var ok = true
            for (ni in k until s[i].length) {
                val nj = ni - k
                if (nj >= s[j].length) break
                if (s[i][ni] == '?' || s[j][nj] == '?') continue
                if (s[i][ni] != s[j][nj]) ok = false
            }
            d[i][j][k] = ok
        }
        fun f(i: Int, j: Int, k: Int) = if (k >= s[i].length) true else d[i][j][k]
        for (x in 0 until MX) for (y in 0 until MX) {
            if (!f(0, 1, x)) continue
            if (!f(1, 2, y)) continue
            if (!f(0, 2, x + y)) continue
            val now = listOf(s[0].length, x + s[1].length, x + y + s[2].length).max()!!
            ans = Math.min(ans, now)
        }
    } while (nextPermutation(s))
    println(ans)
}
fun nextPermutation(a: Array<String>): Boolean {
    for (i in a.size - 1 downTo 1) {
        if (a[i - 1] < a[i]) {
            val swapIndex = find(a[i - 1], a, i, a.size - 1)
            val temp: String = a[swapIndex]
            a[swapIndex] = a[i - 1]
            a[i - 1] = temp
            a.sort(i, a.size)
            return true
        }
    }
    return false
}
private fun find(dest: String, a: Array<String>, s: Int, e: Int): Int {
    if (s == e) return s
    val m = (s + e + 1) / 2
    return if (a[m] <= dest) find(dest, a, s, m - 1) else find(dest, a, m, e)
}
fun next() = readLine()!!