Language: C++

#include <algorithm>
#include <cmath>
#include <functional>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <unordered_map>
#include <vector>

using namespace std;

#define ll long long
#define el '\n'
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define repi(i, a, b) for (int i = a; i >= b; i--)
#define vi vector<int>
#define vii vector<pair<int, int>>
#define pii pair<int, int>
#define mp make_pair
#ifdef NDEBUG
#define debug(fmt, ...)
#define check(...)
#else
#define debug(fmt, ...) printf(fmt, ##__VA_ARGS__)
#define check(...) assert(__VA_ARGS__)
#endif

bool same(char a, char b) {
    return a == b || a == '?' || b == '?';
}

string s[3];
int match_cache[3][3][2000 + 2000 + 10];  // 0: not calculated; 1: match; 2: not match

bool match(int i1, int start, int i2) {
    check(start >= 0);
    if (match_cache[i1][i2][start] != 0) {
        return match_cache[i1][i2][start] == 1 ? true : false;
    }
    string a = s[i1];
    string b = s[i2];
    bool ans = true;
    rep(i, start, a.size() - 1) {
        if (i - start + 1 >= b.size()) {
            break;
        }
        if (!same(a[i], b[i - start])) {
            ans = false;
            break;
        }
    }
    match_cache[i1][i2][start] = ans ? 1 : -1;
    return ans;
}

int solve(int i1, int i2, int i3) {
    string a = s[i1];
    string b = s[i2];
    string c = s[i3];
    int alen = a.size();
    int blen = b.size();
    int clen = c.size();
    int ans = alen + blen + clen;
    // denote s as result of combining a, b, c
    rep(i, 0, alen + max(blen, clen)) {
        // b starts at s[i] and after a
        if (!match(i1, i, i2)) {
            continue;
        }
        rep(j, i, alen + max(blen, clen)) {
            // c starts at s[j] and after b
            if (!match(i1, j, i3) || !match(i2, j - i, i3)) {
                continue;
            }
            int b_end = i + blen - 1;
            int c_end = j + clen - 1;
            int len = max(alen, max(b_end + 1, c_end + 1));
            ans = min(ans, len);
        }
    }
    return ans;
}

string rand_s(int n) {
    string a = "";
    rep(i, 0, n - 1) {
        bool q_mark = rand() < RAND_MAX / 10;
        if (q_mark) {
            a.push_back('?');
        } else {
            char c = rand() % 26 + 'a';
            a.push_back(c);
        }
    }
    return a;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> s[0] >> s[1] >> s[2];

    // int n = 10;
    // srand(time(0));
    // a = rand_s(n);
    // b = rand_s(n);
    // c = rand_s(n);
    // debug("a = %s\n", a.c_str());
    // debug("b = %s\n", b.c_str());
    // debug("c = %s\n", c.c_str());

    // combine a and b first, then consider c
    // permutation
    // so we could assume a then b and c
    int ans = s[0].size() + s[1].size() + s[2].size();
    rep(i, 0, 2) {
        rep(j, 0, 2) {
            if (i != j) {
                rep(k, 0, 2) {
                    if (i != k && j != k) {
                        ans = min(ans, solve(i, j, k));
                    }
                }
            }
        }
    }

    cout << ans << el;
}


Compiler output:
a.cc: In function 'bool match(int, int, int)':
a.cc:26:20: error: 'assert' was not declared in this scope
   26 | #define check(...) assert(__VA_ARGS__)
      |                    ^~~~~~
a.cc:37:5: note: in expansion of macro 'check'
   37 |     check(start >= 0);
      |     ^~~~~
a.cc:8:1: note: 'assert' is defined in header '<cassert>'; this is probably fixable by adding '#include <cassert>'
    7 | #include <queue>
  +++ |+#include <cassert>
    8 | #include <unordered_map>