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)

import java.util.*

fun main(args: Array<String>) {
    val sc = Scanner(System.`in`)
    val s = (1..3).map { sc.next() }
    val c = Array(3) { Array(3) { HashSet<Int>()} }
    for (i in 0 until 3) {
        for (j in 0 until 3) {
            if (i == j) continue
            for (start in s[i].indices) {
                if (check(s[i], s[j], start)) {
                    c[i][j].add(start)
                }
            }
            c[i][j].add(s[i].length)
        }
    }

    var ans = s.map { it.length }.sum()
    for (i in 0 until 3) {
        for (j in 0 until 3) {
            if (i == j) continue
            for (k in 0 until 3) {
                if (i == k || j == k) continue
                ans = Math.min(ans, solve(s, c, listOf(i, j, k)))
            }
        }
    }
    println(ans)
}

fun solve(s: List<String>, c: Array<Array<HashSet<Int>>>, order: List<Int>): Int {
    val s0 = order[0]
    val s1 = order[1]
    val s2 = order[2]

    var ans = s.map { it.length }.sum()
    for (i in c[s0][s1]) {
        for (j in c[s1][s2]) {
            val idx = i + j
            if (idx >= s[s0].length || c[s0][s2].contains(idx)) {
                var len = s[s0].length
                len = Math.max(len, i + s[s1].length)
                len = Math.max(len, idx + s[s2].length)
                ans = Math.min(ans, len)
            }
        }
        for (j in c[s0][s2]) {
            if (j <= i + s[s1].length) continue
            var len = s[s0].length
            len = Math.max(len, j + s[s2].length)
            ans = Math.min(ans, len)
        }
    }
    return ans
}

fun check(a: String, b: String, start: Int): Boolean {
    for (i in b.indices) {
        if (start + i >= a.length) {
            return true
        }
        val ach = a[start + i]
        val bch = b[i]
        if (!(ach == '?' || bch == '?' || ach == bch)) {
            return false
        }
    }
    return true
}