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 Rust (1.15.1) (judge verdict: Accepted)

#![allow(bare_trait_objects)]
#![allow(unused_imports)]
#![allow(dead_code)]

use std::fmt::Debug;
use std::io::BufRead;
use std::io::Stdin;
use std::io::StdinLock;
use std::str::FromStr;

pub struct Scanner<'a> {
    // stdin: Stdin,
    buf_read: Box<BufRead + 'a>,
    tokens: Vec<String>,
}

impl<'a> Scanner<'a> {
    pub fn new(buf_read: StdinLock<'a>) -> Self {
        Scanner {
            buf_read: Box::new(buf_read),
            tokens: Vec::new(),
        }
    }

    // pub fn from_stdin() -> Self {
    //     let stdin = Box::leak(Box::new(std::io::stdin()));
    //     Self {
    //         buf_read: Box::new(stdin.lock()),
    //         tokens: Vec::new(),
    //     }
    // }

    pub fn next(&mut self) -> String {
        while self.tokens.is_empty() {
            let mut s = String::new();
            if self.buf_read.read_line(&mut s).is_err() {
                panic!()
            }
            self.tokens = s
                .split_whitespace()
                .filter(|s| !s.is_empty())
                .rev()
                .map(str::to_string)
                .collect();
        }
        self.tokens.pop().unwrap()
    }

    pub fn next_g<T: FromStr>(&mut self) -> T
    where
        T::Err: Debug,
    {
        self.next().parse().unwrap()
    }

    pub fn next_vec_g<T: FromStr>(&mut self, n: usize) -> Vec<T>
    where
        T::Err: Debug,
    {
        (0..n).map(|_| self.next_g()).collect()
    }

    pub fn usize(&mut self) -> usize {
        self.next_g()
    }

    pub fn i64(&mut self) -> i64 {
        self.next_g()
    }

    pub fn vec_i64(&mut self, n: usize) -> Vec<i64> {
        self.next_vec_g(n)
    }
}
fn main() {
    let stdin = std::io::stdin();
    let mut sc = Scanner::new(stdin.lock());

    let a = sc.next();
    let b = sc.next();
    let c = sc.next();

    let mut ans = 10000000;
    let ss = &[a, b, c];
    for i in 0..3 {
        for j in 0..3 {
            for k in 0..3 {
                if i == j || j == k || i == k {
                    continue;
                }

                let a = &ss[i].chars().collect::<Vec<_>>();
                let b = &ss[j].chars().collect::<Vec<_>>();
                let c = &ss[k].chars().collect::<Vec<_>>();

                let f = |a: &[char], b: &[char]| -> Vec<bool> {
                    let mut okij = vec![true; 6001];
                    for i in 0..a.len() {
                        okij[i] = true;
                        for j in 0..b.len() {
                            if i + j < a.len() && a[i + j] != b[j] && a[i + j] != '?' && b[j] != '?'
                            {
                                okij[i] = false;
                                break;
                            }
                        }
                    }
                    okij
                };

                let okij = f(a, b);
                let okik = f(a, c);
                let okjk = f(b, c);

                // eprintln!("{:?}", &okij[0..5]);
                // eprintln!("{:?}", &okik[0..5]);
                // eprintln!("{:?}", &okjk[0..5]);

                for i in 0..a.len() + 1 {
                    for j in 0..std::cmp::max(a.len() - i, b.len()) + 1 {
                        if okij[i] && okik[i + j] && okjk[j] {
                            ans = std::cmp::min(
                                ans,
                                *[a.len(), i + b.len(), i + j + c.len()]
                                    .iter()
                                    .max()
                                    .unwrap(),
                            );
                        }
                    }
                }
            }
        }
    }

    println!("{}", ans);
}