#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <set>
#include <map>
#include <vector>
#include <string>

using namespace std;

string a, b, c;

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

vector<int> getCross(string a, string b) {
	vector<int> res;
	res.clear();
	int al = a.length(), bl = b.length();
	for (int i = 0; i <= min(al, bl); ++i) {
		bool flag = true;
		for (int j = 0; j < i; ++j) {
			char ca = a[al - i + j], cb = b[j];
			if (!same(ca, cb)) {
				flag = false;
				break;
			}
		}
		if (flag) {
			res.push_back(i);
		}
	}
	return res;
}

int getAns(string a, string b, string c) {
	vector<int> cab = getCross(a, b), cbc = getCross(b, c);
	/*cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;
	for (int i = 0; i < cab.size(); ++i) {
		cout << cab[i] << ' ';
	}
	cout << endl;
	for (int i = 0; i < cbc.size(); ++i) {
		cout << cbc[i] << ' ';
	}
	cout << endl;*/
	int ans = a.length() + b.length() + c.length();
	int tl = ans;
	int lb = b.length();
	for (int i = cab.size() - 1; i >= 0; --i) {
		for (int j = cbc.size() - 1; j >= 0; --j) {
			int lab = cab[i], lbc = cbc[j];
			if (lab + lbc <= lb) {
				ans = min(ans, tl - lab - lbc);
				break;
			}
			// [0, lab), [lb - lbc, lb)
			bool flag = true;
			for (int k = lb - lbc; k < lab; ++k) {
				if (b[k] != '?') {
					continue;
				}
				char ca = a[a.length() - lab + k];
				char cb = c[k - (lb - lbc)];
				if (!same(ca, cb)) {
					flag = false;
					break;
				}
			}
			if (flag) {
				ans = min(ans, tl - lab - lbc);
				break;
			}
		}
	}
	return ans;
}
bool cmp(const string &a, const string &b) {
	return a.length() > b.length();
}
vector<int> getContains(string a, string b) {
	vector<int> res;
	for (int i = 0; i <= a.length() - b.length(); ++i) {
		bool flag = true;
		for (int j = 0; j < b.length(); ++j) {
			if (!same(a[i + j], b[j])) {
				flag = false;
				break;
			}
		}
		if (flag) {
			res.push_back(i);
		}
	}
	return res;
}
int KMP(string a, string b) {
	// cout << "kmp " << a << " " << b << endl;
	// first, make a next array for b
	/* vector<int> nxt;
	nxt.clear();
	int n = b.length();
	nxt.push_back(-1);

	for (int i = 0; i < n - 1; ++i) {
		int p = nxt[i];
		while (p >= 0 && !same(b[p], b[i])) {
			p = nxt[p];
		}
		nxt.push_back(p + 1);
	}
	cout << "next: ";
	for (int i = 0; i < nxt.size(); ++i) {
		cout << nxt[i] << ' ';
	}
	cout << endl;
	int p = 0, q = 0;
	while (p < a.length()) {
		if (q == b.length()) {
			return q;
		}
		if (q == -1 || same(a[p], b[q])) {
			++p; ++q;
		}
		else {
			q = nxt[q];
		}
		printf("p = %d, q = %d\n", p, q);
	} */
	for (int i = 0; i < a.length(); ++i) {
		bool flag = true;
		for (int j = 0; j < min(a.length() - i, b.length()); ++j) {
			if (!same(a[i + j], b[j])) {
				flag = false;
				break;
			}
		}
		if (flag) {
			return min(a.length() - i, b.length());
		}
	}
	return 0;
}
int getContact(string a, string b) {
	// a.length() > b.length()
	// 3 conditions: a contains b, a at the beginning of b, a at the end of b
	// for 1. just kmp over a, b
	// for 2. kmp over a, b, find the length when a ends 
	// for 3. kmp over b, a, find the length when a ends

	// we need: a kmp function(a, b), if matched return b.length(), else return the matched length at the end of a
	int ans = a.length() + b.length();
	int tl = ans, kmpRes = 0;
	kmpRes = KMP(a, b);
	// cout << "KMP (" << a << ", " << b << ") = " << kmpRes << endl;
	ans = min(ans, tl - kmpRes);
	kmpRes = KMP(b, a);
	// cout << "KMP (" << b << ", " << a << ") = " << kmpRes << endl;
	ans = min(ans, tl - kmpRes);
	return ans;
}
int getRes(vector<int> pp, string a, string b, string c) {
	string aTmp = a;
	int ans = a.length() + b.length() + c.length();
	for (int i = 0; i < pp.size(); ++i) {
		for (int j = 0; j < b.length(); ++j) {
			if (a[pp[i] + j] == '?' && b[j] != '?') {
				a[pp[i] + j] = b[j];
			}
		}
		ans = min(ans, getContact(a, c));
		for (int j = 0; j < b.length(); ++j) {
			a[pp[i] + j] = aTmp[pp[i] + j];
		}
	}
	return ans;
}
int getContainAns(string a, string b, string c) {
	vector<string> ss;
	ss.push_back(a); ss.push_back(b); ss.push_back(c);
	sort(ss.begin(), ss.end(), cmp);
	int ans = a.length() + b.length() + c.length();

	a = ss[0]; b = ss[1]; c = ss[2];
	vector<string> containS;
	ans = min(ans, getRes(getContains(a, b), a, b, c));
	ans = min(ans, getRes(getContains(a, c), a, c, b));
	ans = min(ans, getRes(getContains(b, c), b, c, a));
	return ans;

}
int main() {
	cin >> a >> b >> c;
	int la, lb, lc;
	la = a.length(); lb = b.length(); lc = c.length();
	int ans = la + lb + lc;

	ans = min(ans, getAns(a, b, c));
	ans = min(ans, getAns(a, c, b));
	ans = min(ans, getAns(b, a, c));
	ans = min(ans, getAns(b, c, a));
	ans = min(ans, getAns(c, a, b));
	ans = min(ans, getAns(c, b, a));

	ans = min(ans, getContainAns(a, b, c));
	cout << ans << endl;
	
	return 0;
}

Measured memory_bytes: 384