Problem:
Problem F:
City Merger
Recent improvements in information and communication technology have made it possible to provide municipal service to a wider area more quickly and with less costs. Stimulated by this, and probably for saving their not sufficient funds, mayors of many cities started to discuss on mergers of their cities.
There are, of course, many obstacles to actually put the planned mergers in practice. Each city has its own culture of which citizens are proud. One of the largest sources of friction is with the name of the new city. All citizens would insist that the name of the new city should have the original name of their own city at least as a part of it. Simply concatenating all the original names would, however, make the name too long for everyday use.
You are asked by a group of mayors to write a program that finds the shortest possible name for the new city that includes all the original names of the merged cities. If two or more cities have common parts, they can be overlapped. For example, if "FUKUOKA", "OKAYAMA", and "YAMAGUCHI" cities are to be merged, "FUKUOKAYAMAGUCHI" is such a name that include all three of the original city names. Although this includes all the characters of the city name "FUKUYAMA" in this order, it does not appear as a consecutive substring, and thus "FUKUYAMA" is not considered to be included in the name.
Input
The input is a sequence of datasets. Each dataset begins with a line containing a positive integer
n
(
n
≤ 14), which denotes the number of cities to be merged. The following
n
lines contain the names of the cities in uppercase alphabetical letters, one in each line. You may assume that none of the original city names has more than 20 characters. Of course, no two cities have the same name.
The end of the input is indicated by a line consisting of a zero.
Output
For each dataset, output the length of the shortest possible name of the new city in one line. The output should not contain any other characters.
Sample Input
3
FUKUOKA
OKAYAMA
YAMAGUCHI
3
FUKUOKA
FUKUYAMA
OKAYAMA
2
ABCDE
EDCBA
4
GA
DEFG
CDDE
ABCD
2
ABCDE
C
14
AAAAA
BBBBB
CCCCC
DDDDD
EEEEE
FFFFF
GGGGG
HHHHH
IIIII
JJJJJ
KKKKK
LLLLL
MMMMM
NNNNN
0
Output for the Sample Input
16
19
9
9
5
70

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;

int n;
vector<int> ls;
vector<vector<int>> v; // v[i][j] = overlap length a[i] suffix vs a[j] prefix
unordered_map<long long,int> cac; // memo for sediv
unordered_map<int,int> bp; // single-bit -> index

const int INF = 1000000000;

long long make_key(int st, int en, int tp) {
    // replicate Python: cachenm = st + en*n + tp*n*n
    long long nn = (long long)n * (long long)n;
    return (long long)tp * nn + (long long)en * n + st;
}

int sediv(int st, int en, int tp) {
    long long key = make_key(st,en,tp);
    auto it = cac.find(key);
    if (it != cac.end()) return it->second;

    if (tp == 0) {
        int tmp = ls[st] + ls[en] - v[st][en];
        cac[key] = tmp;
        return tmp;
    }
    auto itbp = bp.find(tp);
    if (itbp != bp.end()) {
        int a = itbp->second;
        int tmp = ls[st] + ls[a] + ls[en] - v[st][a] - v[a][en];
        cac[key] = tmp;
        return tmp;
    }

    int mn = INF;
    for (int i = 0; i < n-1; ++i) {
        if (!(tp & (1<<i))) continue;
        for (int j = i+1; j < n; ++j) {
            if (!(tp & (1<<j))) continue;
            int tp2 = tp & ~( (1<<i) | (1<<j) );
            int tmp1 = sediv(i,j,tp2) - v[st][i] - v[j][en];
            int tmp2 = sediv(j,i,tp2) - v[st][j] - v[i][en];
            int cur = min(tmp1, tmp2);
            if (cur < mn) mn = cur;
        }
    }
    mn += ls[st] + ls[en];
    cac[key] = mn;
    return mn;
}

// overlap function same as Python sc
int sc_str_overlap(const string &a, const string &b) {
    int lna = (int)a.size();
    int lnb = (int)b.size();
    for (int i = 0; i < (int)a.size(); ++i) {
        if (lnb + i <= lna) continue;
        int len = lna - i;
        // compare a[i:] with b[:len]
        bool ok = true;
        for (int k = 0; k < len; ++k) {
            if (a[i+k] != b[k]) { ok = false; break; }
        }
        if (ok) return len;
    }
    return 0;
}

// generate next combination in lexicographic order
// a: current indices (size k), n: range, returns false if no next
bool next_combination(vector<int> &a, int n, int k) {
    for (int i = k-1; i >= 0; --i) {
        if (a[i] != i + n - k) {
            ++a[i];
            for (int j = i+1; j < k; ++j) a[j] = a[j-1] + 1;
            return true;
        }
    }
    return false;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    // prepare bp
    for (int i = 0; i < 15; ++i) bp[1<<i] = i;

    while (true) {
        if (!(cin >> n)) return 0;
        if (n == 0) return 0;
        vector<string> s;
        s.reserve(n);
        for (int i = 0; i < n; ++i) {
            string t; cin >> t;
            s.push_back(t);
        }

        // dpl: remove strings fully contained in others
        {
            vector<char> removed(n, 0);
            for (int i = 0; i < n; ++i) {
                if (removed[i]) continue;
                for (int j = 0; j < n; ++j) {
                    if (i == j || removed[j]) continue;
                    if (s[i].size() <= s[j].size()) {
                        // check if s[i] is substring of s[j]
                        if (s[j].find(s[i]) != string::npos) {
                            removed[i] = 1;
                            break;
                        }
                    }
                }
            }
            vector<string> ns;
            for (int i = 0; i < n; ++i) if (!removed[i]) ns.push_back(s[i]);
            s.swap(ns);
        }

        n = (int)s.size();
        if (n == 0) { cout << 0 << '\n'; continue; }

        // build v
        v.assign(n, vector<int>(n,0));
        if (n == 1) {
            cout << s[0].size() << '\n';
            continue;
        }
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (i == j) continue;
                v[i][j] = sc_str_overlap(s[i], s[j]);
            }
        }
        ls.assign(n,0);
        for (int i = 0; i < n; ++i) ls[i] = (int)s[i].size();

        if (n <= 3) {
            // brute force permutations to get maximum overlaps sum
            vector<int> perm(n);
            for (int i = 0; i < n; ++i) perm[i] = i;
            int best = 0;
            do {
                int sum = 0;
                for (int i = 0; i+1 < n; ++i) sum += v[perm[i]][perm[i+1]];
                best = max(best, sum);
            } while (next_permutation(perm.begin(), perm.end()));
            int total_len = 0;
            for (int x : ls) total_len += x;
            cout << (total_len - best) << '\n';
            continue;
        }

        cac.clear();

        int div2 = n/2;
        int div3 = n - div2;
        int sm = (1<<n);

        // prepare initial combination [0,1,...,div2-1]
        vector<int> comb(div2);
        for (int i = 0; i < div2; ++i) comb[i] = i;

        int ans = INF;

        bool first = true;
        while (true) {
            // comb is current combination in lexicographic order
            if (!first) {
                // already advanced
            }
            first = false;

            // replicate Python's: if i[0] != 0: break
            if (comb[0] != 0) break;

            int gr0 = 0;
            for (int x : comb) gr0 |= (1<<x);
            int gr1 = (sm - 1) ^ gr0; // complement within n bits

            // lga, lgb: store sediv results for start-end pairs
            // use 2D vectors filled with INF
            vector<vector<int>> lga(n, vector<int>(n, INF));
            vector<vector<int>> lgb(n, vector<int>(n, INF));

            // for gr0: iterate all pairs i<j that exist in gr0
            for (int i = 0; i < n-1; ++i) {
                if (!(gr0 & (1<<i))) continue;
                for (int j = i+1; j < n; ++j) {
                    if (!(gr0 & (1<<j))) continue;
                    int msk = gr0 & ~( (1<<i) | (1<<j) );
                    lga[i][j] = sediv(i,j,msk);
                    lga[j][i] = sediv(j,i,msk);
                }
            }

            // for gr1: same
            for (int i = 0; i < n-1; ++i) {
                if (!(gr1 & (1<<i))) continue;
                for (int j = i+1; j < n; ++j) {
                    if (!(gr1 & (1<<j))) continue;
                    int msk = gr1 & ~( (1<<i) | (1<<j) );
                    lgb[i][j] = sediv(i,j,msk);
                    lgb[j][i] = sediv(j,i,msk);
                }
            }

            int mn = INF;
            // iterate over valid (sta,ena) in lga and (stb,enb) in lgb
            for (int sta = 0; sta < n; ++sta) {
                for (int ena = 0; ena < n; ++ena) {
                    if (lga[sta][ena] == INF) continue;
                    for (int stb = 0; stb < n; ++stb) {
                        for (int enb = 0; enb < n; ++enb) {
                            if (lgb[stb][enb] == INF) continue;
                            // two combinations as in python
                            int tmp = lga[sta][ena] + lgb[stb][enb] - v[ena][stb];
                            if (tmp < mn) mn = tmp;
                            tmp = lga[sta][ena] + lgb[stb][enb] - v[enb][sta];
                            if (tmp < mn) mn = tmp;
                        }
                    }
                }
            }
            if (mn < ans) ans = mn;

            // advance combination
            if (!next_combination(comb, n, div2)) break;
        }

        cout << ans << '\n';
    }

    return 0;
}
accuracy: 1
time_ms: 3510
memory_kb: 10704
final_rank: 17

code_snippet: #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>

using namespace std;

const int maxn = 30;

int n;
int extra[maxn][maxn], f[1<<15][maxn];
char word[maxn][maxn];
bool substr[maxn];
vector<char*> wd;

int main()
{
#ifdef LOCAL
	freopen("F.in", "r", stdin);
#endif
	while(scanf("%d", &n) != EOF) {
		if(n == 0)	break;
		memset(substr, 0, n*sizeof(char));
		wd.clear();
		for(int i = 0; i < n; i++) {
			scanf("%s", word+i);
			for(int j = 0; j < i; j++) {
				if(strstr(word[i], word[j]) != NULL)	substr[j] = true;
				else if(strstr(word[j], word[i]) != NULL)	substr[i] = true;
			}
		}
		for(int i = 0; i < n; i++)
			if(!substr[i])	wd.push_back(word[i]);
		for(int i = 0; i < wd.size(); i++)
			for(int j = 0; j < wd.size(); j++) {
				int plen = strlen(wd[i]), nlen = strlen(wd[j]), match = 0;
				for(int k = min(nlen, plen); k > 0; k--)
					if(strncmp(wd[j], wd[i]+plen-k, k) == 0)	{
						match = k;
						break;
					}
				extra[i][j] = nlen-match;
			}
		int cnt = wd.size();
		memset(f, 0, sizeof(f));
		for(int i = 0; i < cnt; i++)
			f[1<<i][i] = strlen(wd[i]);
		for(int i = 1; i < (1 << cnt); i++) 
			for(int j = 0; j < cnt; j++) {
				if(((1<<j)&i) == 0)	continue; 
				for(int k = 0; k < cnt; k++) {
					if((1<<k)&i)	continue; 
					int now = i|(1<<k); 
					f[now][k] = f[now][k]? min(f[now][k], f[i][j]+extra[j][k]):f[i][j]+extra[j][k]; 
//					if(i == 13)
//					cout << "Insert " <<  k << " after " << j << ' ' << f[now][k] << endl; 
				} 
			} 
		int ans = cnt*maxn; 
		for(int i = 0; i < cnt; i++) 
			ans = min(ans, f[(1<<cnt)-1][i]); 
		printf("%d\n", ans); 
	}
	return 0; 
}
accuracy: 1
time_ms: 150
memory_kb: 7416
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

int main() {
while(1) {
    int N;
    cin >> N;
    if (N == 0) return 0;
    vector<string> T(N);
    rep(i,0,N) cin >> T[i];
    vector<string> S;
    rep(i,0,N) {
        bool check = true;
        rep(j,0,N) {
            if (i==j) continue;
            if (T[i].size() > T[j].size()) continue;
            rep(k,0,T[j].size()) {
                if (k+(int)T[i].size() > (int)T[j].size()) break;
                if (T[j].substr(k,T[i].size()) == T[i]) check = false;
            }
        }
        if (check) S.push_back(T[i]);
    }
    N = S.size();
    vector<vector<int>> G(N,vector<int>(N,inf));
    rep(i,0,N) {
        rep(j,0,N) {
            if (i == j) {
                G[i][j] = 0;
                continue;
            }
            rep(k,0,min(S[i].size(),S[j].size())) {
                if (S[i].substr(S[i].size()-k,k) == S[j].substr(0,k)) G[i][j] = (int)S[j].size() - k;
            }
        }
    }
    vector DP(1<<N, vector<int>(N,inf));
    rep(i,0,N) DP[1<<i][i] = S[i].size();
    rep(i,1,1<<N) {
        rep(j,0,N) {
            if (DP[i][j] == inf) continue;
            rep(k,0,N)  {
                if (i & (1<<k)) continue;
                chmin(DP[i|(1<<k)][k],DP[i][j]+G[j][k]);
            }
        }
    }
    int ANS = inf;
    rep(i,0,N) chmin(ANS, DP[(1<<N)-1][i]);
    cout << ANS << endl;
}
}
accuracy: 1
time_ms: 190
memory_kb: 4740
final_rank: 7

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < n; i++)

int calcdif(string s, string t) { // 文字列tの長さ - 文字列sと文字列tの共通部分の長さ
    int sz = s.size();
    int tz = t.size();
    int comlen = 0;
    for (int i = 0; i < sz; i++) { // sのiからszまでとtの0からlenまでの共通部分の長さを計算する
        for (int len = 1; len <= tz; len++) {
            string ss = s.substr(i, sz);
            string tt = t.substr(0, len);
            if (ss == tt) {
                comlen = max(comlen, len);
            }
        }
    }

    return tz - comlen;
}

int main() {
    int n;
    while(cin >> n && n) {
        vector<string> cities(n);
        rep(i, n) cin >> cities[i];

        vector<int> unIncludedCities; // 互いに部分文字列になっていない都市のリスト

        rep(i, n) { // 都市iが他の都市の部分文字列になってないなら、unIncludedCitiesに追加
            bool isInclude = false;
            rep(j, n) {
                if(i == j) continue;
                if(cities[j].find(cities[i]) != string::npos) {
                    isInclude = true;
                    break;
                }
            }
            if(!isInclude) unIncludedCities.push_back(i);
        }

        int m = unIncludedCities.size();

        vector<vector<int>> dif(m, vector<int>(m)); // dif[i][j] := 都市jの長さ - 都市iの末尾と都市jの先頭の重複する部分の長さ
        rep(i, m) rep(j, m) {
            dif[i][j] = calcdif(cities[unIncludedCities[i]], cities[unIncludedCities[j]]);
        }

        vector<vector<int>> dp((1 << m), vector<int>(m, 1e9)); // dp[i][j] := 集合iを訪れて都市jにいるときの統合された文字列の最小の長さ
        rep(i, m) dp[1 << i][i] = cities[unIncludedCities[i]].size(); // 初期値が都市iのとき、都市iの長さを格納

        rep(i, (1 << m)) rep(j, m) {
            if(!(i & (1 << j))) continue;
            rep(k, m) {
                if(i & (1 << k)) continue;
                dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + dif[j][k]);
            }
        }

        cout << *min_element(dp[(1 << m) - 1].begin(), dp[(1 << m) - 1].end()) << endl;
    }
}
accuracy: 1
time_ms: 180
memory_kb: 4620
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
using uint = unsigned;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
using pdd = pair<ld, ld>;
using tuplis = array<ll, 3>;
template<class T> using pq = priority_queue<T, vector<T>, greater<T>>;
const ll LINF=0x1fffffffffffffff;
const ll MINF=0x7fffffffffff;
const int INF=0x3fffffff;
const int MOD=1000000007;
const int MODD=998244353;
const ld DINF=numeric_limits<ld>::infinity();
const ld EPS=1e-9;
const ld PI=3.14159265358979323846;
const ll dx[] = {0, 1, 0, -1, 1, -1, 1, -1};
const ll dy[] = {1, 0, -1, 0, 1, 1, -1, -1};
#define overload5(a,b,c,d,e,name,...) name
#define overload4(a,b,c,d,name,...) name
#define overload3(a,b,c,name,...) name
#define rep1(n) for(ll i=0;i<n;++i)
#define rep2(i,n) for(ll i=0;i<n;++i)
#define rep3(i,a,b) for(ll i=a;i<b;++i)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=n;i--;)
#define rrep2(i,n) for(ll i=n;i--;)
#define rrep3(i,a,b) for(ll i=b;i-->(a);)
#define rrep4(i,a,b,c) for(ll i=(a)+((b)-(a)-1)/(c)*(c);i>=(a);i-=c)
#define rrep(...) overload4(__VA_ARGS__,rrep4,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define each1(i,a) for(auto&&i:a)
#define each2(x,y,a) for(auto&&[x,y]:a)
#define each3(x,y,z,a) for(auto&&[x,y,z]:a)
#define each4(w,x,y,z,a) for(auto&&[w,x,y,z]:a)
#define each(...) overload5(__VA_ARGS__,each4,each3,each2,each1)(__VA_ARGS__)
#define all1(i) begin(i),end(i)
#define all2(i,a) begin(i),begin(i)+a
#define all3(i,a,b) begin(i)+a,begin(i)+b
#define all(...) overload3(__VA_ARGS__,all3,all2,all1)(__VA_ARGS__)
#define rall1(i) rbegin(i),rend(i)
#define rall2(i,a) rbegin(i),rbegin(i)+a
#define rall3(i,a,b) rbegin(i)+a,rbegin(i)+b
#define rall(...) overload3(__VA_ARGS__,rall3,rall2,rall1)(__VA_ARGS__)
#define sum(...) accumulate(all(__VA_ARGS__),0LL)
#define dsum(...) accumulate(all(__VA_ARGS__),0.0L)
#define Msum(...) accumulate(all(__VA_ARGS__),mint{})
#define elif else if
#define INT(...) int __VA_ARGS__;in(__VA_ARGS__)
#define LL(...) ll __VA_ARGS__;in(__VA_ARGS__)
#define ULL(...) ull __VA_ARGS__;in(__VA_ARGS__)
#define STR(...) string __VA_ARGS__;in(__VA_ARGS__)
#define CHR(...) char __VA_ARGS__;in(__VA_ARGS__)
#define DBL(...) double __VA_ARGS__;in(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__;in(__VA_ARGS__)
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define VEC(type,name,size) vector<type>name(size);in(name)
#define vv(type,name,h,...) vector name(h,vector<type>(__VA_ARGS__))
#define VV(type,name,h,w) vector name(h,vector<type>(w));in(name)
#define vvv(type,name,h,w,...) vector name(h,vector(w,vector<type>(__VA_ARGS__)))
template<class T> ll sz(const T& a){ return size(a); }
template<class T> auto min(const T& a){ return *min_element(all(a)); }
template<class T> auto max(const T& a){ return *max_element(all(a)); }
template<class T, class U> ll count(const T& a, const U& b){ return count(all(a), b); }
template<class T, class F> ll count_if(const T& a, F b){ return count_if(all(a), b); }
template<class T, class F> void filter(T& a, F b){ a.erase(remove_if(all(a), not_fn(b)), a.end()); }
template<class T, class F = less<>> void sor(T& a, F b = F{}){ sort(all(a), b); }
template<class T> void rev(T& a){ reverse(all(a)); }
template<class T> void uniq(T& a){ sor(a); a.erase(unique(all(a)), end(a)); }
ll popcnt(ull a){ return __builtin_popcountll(a); }
ll intpow(ll a, ll b){ ll ans = 1; while(b){ if(b & 1) ans *= a; a *= a; b /= 2; } return ans; }
ll modpow(ll a, ll b, ll p){ ll ans = 1; while(b){ if(b & 1) (ans *= a) %= p; (a *= a) %= p; b /= 2; } return ans; }
template<class T> T div_floor(T a, T b) { return a / b - ((a ^ b) < 0 && a % b); }
template<class T> T div_ceil(T a, T b) { return a / b + ((a ^ b) > 0 && a % b); }
template<class T> bool chmin(T& a, const T& b){ if(a <= b) return 0; a = b; return 1; }
template<class T> bool chmax(T& a, const T& b){ if(a >= b) return 0; a = b; return 1; }
template<class T, class U> bool chmin(T& a, const U& b){ return chmin(a, (T)b); }
template<class T, class U> bool chmax(T& a, const U& b){ return chmax(a, (T)b); }
vector<ll> iota(ll n, ll begin = 0){ vector<ll> a(n); iota(a.begin(), a.end(), begin); return a; }
vector<pll> factor(ull x){ vector<pll> ans; for(ull i = 2; i * i <= x; i++) if(x % i == 0){ ans.push_back({i, 1}); while((x /= i) % i == 0) ans.back().second++; } if(x != 1) ans.push_back({x, 1}); return ans; }
vector<ll> divisor(ull x){ vector<ll> ans; for(ull i = 1; i * i <= x; i++) if(x % i == 0) ans.push_back(i); rrep(ans.size() - (ans.back() * ans.back() == x)) ans.push_back(x / ans[i]); return ans; }
template<class T> unordered_map<T, ll> press(vector<T> a){ uniq(a); unordered_map<T, ll> ans; rep(a.size()) ans[a[i]] = i; return ans; }
template<class T> auto run_press(const T& a){ vector<pair<decay_t<decltype(a[0])>, ll>> ans; each(x, a){ if(ans.empty() || ans.back().first != x) ans.emplace_back(x, 1); else ans.back().second++; } return ans; }
template<class... Ts> void in(Ts&... t);
[[maybe_unused]] void print(){}
template<class T, class... Ts> void print(const T& t, const Ts&... ts);
template<class... Ts> void out(const Ts&... ts){ print(ts...); cout << '\n'; }
namespace IO{
#define VOID(a) decltype(void(a))
struct S{ S(){ cin.tie(nullptr)->sync_with_stdio(0); fixed(cout).precision(12); } }S;
template<int I> struct P : P<I-1>{};
template<> struct P<0>{};
template<class T> void i(T& t){ i(t, P<3>{}); }
void i(vector<bool>::reference t, P<3>){ int a; i(a); t = a; }
template<class T> auto i(T& t, P<2>) -> VOID(cin >> t){ cin >> t; }
template<class T> auto i(T& t, P<1>) -> VOID(begin(t)){ for(auto&& x : t) i(x); }
template<class T, size_t... idx> void ituple(T& t, index_sequence<idx...>){ in(get<idx>(t)...); }
template<class T> auto i(T& t, P<0>) -> VOID(tuple_size<T>{}){ ituple(t, make_index_sequence<tuple_size<T>::value>{}); }
template<class T> void o(const T& t){ o(t, P<4>{}); }
template<size_t N> void o(const char (&t)[N], P<4>){ cout << t; }
template<class T, size_t N> void o(const T (&t)[N], P<3>){ o(t[0]); for(size_t i = 1; i < N; i++){ o(' '); o(t[i]); } }
template<class T> auto o(const T& t, P<2>) -> VOID(cout << t){ cout << t; }
template<class T> auto o(const T& t, P<1>) -> VOID(begin(t)){ bool first = 1; for(auto&& x : t) { if(first) first = 0; else o(' '); o(x); } }
template<class T, size_t... idx> void otuple(const T& t, index_sequence<idx...>){ print(get<idx>(t)...); }
template<class T> auto o(T& t, P<0>) -> VOID(tuple_size<T>{}){ otuple(t, make_index_sequence<tuple_size<T>::value>{}); }
#undef VOID
}
#define unpack(a) (void)(0 + ... + (a, 0))
template<class... Ts> void in(Ts&... t){ unpack(IO::i(t)); }
template<class T, class... Ts> void print(const T& t, const Ts&... ts){ IO::o(t); unpack(IO::o((cout << ' ', ts))); }
#undef unpack
#ifdef DEBUG
ll __lg(ull x){ return 63 - __builtin_clzll(x); }
#define debug(...) { print(#__VA_ARGS__); print(
#else
#define debug(...) void(0)
#endif
#define YESNO(yes,no) void yes(bool i = 1){ out(i?#yes:#no); } void no(){ out(#no); }
YESNO(first, second)
YESNO(First, Second)
YESNO(Yes, No)
YESNO(YES, NO)
YESNO(possible, impossible)
YESNO(Possible, Impossible)
YESNO(POSSIBLE, IMPOSSIBLE)



template<class T> using P = pair<T, T>;
#define x first
#define y second
template<class T> P<T> operator+(const P<T>& a, const P<T>& b) { return {a.x + b.x, a.y + b.y}; }
template<class T> P<T> operator-(const P<T>& a, const P<T>& b) { return {a.x - b.x, a.y - b.y}; }
template<class T> P<T> operator-(const P<T>& a) { return {-a.x, -a.y}; }
template<class T, class U> P<T> operator*(const P<T>& a, const U& b) { return {a.x * b, a.y * b}; }
template<class T, class U> P<T> operator/(const P<T>& a, const U& b) { return {a.x / b, a.y / b}; }
template<class T> P<T>& operator+=(P<T>& a, const P<T>& b) { return a = a + b; }
template<class T> P<T>& operator-=(P<T>& a, const P<T>& b) { return a = a - b; }
template<class T, class U> P<T>& operator*=(P<T>& a, const U& b) { return a = a * b; }
template<class T, class U> P<T>& operator/=(P<T>& a, const U& b) { return a = a / b; }
template<class T> P<T> rotate(const P<T>& a) { return {-a.y, a.x}; } // 90 degree ccw
template<class T> T dot(const P<T>& a, const P<T>& b) { return a.x * b.x + a.y * b.y; }
template<class T> T cross(const P<T>& a, const P<T>& b) { return dot(rotate(a), b); }
template<class T> T square(const P<T>& a) { return dot(a, a); }
template<class T> ld abs(const P<T>& a) { return hypotl(a.x, a.y); }
template<class T> T gcd(const P<T>& a) { return gcd(a.x, a.y); }
template<class T> P<T> normalize(P<T> a) {
    if(a == P<T>{}) return a;
    a /= gcd(a);
    if(a < P<T>{}) a = -a;
    return a;
}

// 文字列tの長さ - 文字列sと文字列tの共通部分の長さ
int calcdif(string s, string t) {
    int sz = s.size();
    int tz = t.size();
    int comlen = 0;
    for (int i = 0; i < sz; i++) { // sのiからszまでとtの0からlenまでの共通部分の長さを計算する
        for (int len = 1; len <= tz; len++) {
            string ss = s.substr(i, sz);
            string tt = t.substr(0, len);
            if (ss == tt) {
                comlen = max(comlen, len);
            }
        }
    }

    // // tがsに含まれている場合、末尾に付け足す文字列の長さは0
    // for (int len = 1; len <= sz; len++) {
    //     for (int i = 0; i < sz; i++) {
    //         string ss = s.substr(i, len);
    //         string tt = t.substr(0, tz);
    //         if (ss == tt) {
    //             return 0;
    //         }
    //     }
    // }

    return tz - comlen;
}

int main() {
    int n;
    while(cin >> n && n) {
        vector<string> str(n+1);
        for (int i = 1; i <= n; i++) cin >> str[i];

        vector<string> rms;
        // 他の文字列に含まれていない文字列を抽出
        for (int i = 1; i <= n; i++) {
            bool flag = false;
            for (int j = 1; j <= n; j++) {
                if (i == j) continue;
                for (int len = 1; len <= str[j].size(); len++) {
                    for (int k = 0; k + len <= str[j].size(); k++) {
                        if (str[j].substr(k, len) == str[i]) {
                            flag = true;
                            break;
                        }
                    }
                }
            }
            if (!flag) rms.push_back(str[i]);
        }
        // out(rms);
        
        int m = rms.size();
        // dif[i][j] 文字列jの長さ - 文字列iと文字列jの共通部分の長さ
        vector<vector<int>> dif(n+1, vector<int>(n+1, 0));
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < m; j++) {
                if (i == j) continue;
                dif[i][j] = calcdif(rms[i], rms[j]);
            }
        }

        // rep(i, m) {
        //     rep(j, m) {
        //         cout << dif[i][j] << " ";
        //     }
        //     cout << endl;
        // }

        // // dp[i][j] すでに状態iなる文字列を使っていて、現在位置がjであるときの併合した文字列の長さの最小値
        vector<vector<int>> dp((1<<14)+1, vector<int>(n+1, INF));
        for (int i = 0; i < m; i++) dp[(1<<i)][i] = rms[i].size();
        for (int i = 1; i < (1<<m); i++) { // すでに使っている文字列の集合
            for (int j = 0; j <= m; j++) { // 現在位置
                if (dp[i][j] == INF) continue;
                for (int k = 0; k < m; k++) { // 併合する文字列を選ぶ
                    if (i & (1<<(k))) continue; // すでに使っている文字列は使えない
                    chmin(dp[i|(1<<(k))][k], dp[i][j] + dif[j][k]);
                }
            }
        }
        out(*min_element(all(dp[(1<<m)-1])));
    }
}
accuracy: 1
time_ms: 290
memory_kb: 4748
final_rank: 12

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

int solve(int n) {
    vector<string> s = in(n);
    {
        vector<string> ns;
        for(int i : rep(n)) {
            bool substr = false;
            for(int j : rep(n)) if(j != i and s[i].size() <= s[j].size()) {
                for(int k : rep(s[j].size())) {
                    if(s[j].substr(k, s[i].size()) == s[i]) {
                        substr = true;
                    }
                }
            }
            if(!substr) ns.push_back(s[i]);
        }
        s = move(ns);
        n = s.size();
    }

    vector dp(1 << n, vector(n, int(1e9)));
    for(int i : rep(n)) dp[1 << i][i] = s[i].size();

    vector c(n, vector(n, int(1e9)));
    for(int i : rep(n)) for(int j : rep(n)) if(i != j) {
        for(int k : revrep(int(s[i].size()))) {
            if(s[i].substr(s[i].size() - k, k) == s[j].substr(0, k)) {
                c[i][j] = s[j].size() - k;
                break;
            }
        }
    }

    for(int S : rep(1 << n)) if(S) {
        for(int i : rep(n)) if(S & (1 << i)) {
            for(int j : rep(n)) if(!(S & (1 << j))) {
                chmin(dp[S | (1 << j)][j], dp[S][i] + c[i][j]);
            }
        }
    }

    int ans = 1e9;
    for(int i : rep(n)) chmin(ans, dp[(1 << n) - 1][i]);
    return ans;
}

int main() {
    while(true) {
        int n = in(); if(n == 0) break;
        print(solve(n));
    }
}
accuracy: 1
time_ms: 170
memory_kb: 4884
final_rank: 5

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

} // namespace macro

using namespace macro;
#line 3 "A.cpp"

int solve(int n) {
    vector<string> s = in(n);
    {
        vector<string> ns;
        for(int i : rep(n)) {
            bool substr = false;
            for(int j : rep(n)) if(j != i and s[i].size() <= s[j].size()) {
                for(int k : rep(s[j].size())) {
                    if(s[j].substr(k, s[i].size()) == s[i]) {
                        substr = true;
                    }
                }
            }
            if(!substr) ns.push_back(s[i]);
        }
        s = move(ns);
        n = s.size();
    }

    vector dp(1 << n, vector(n, int(1e9)));
    for(int i : rep(n)) dp[1 << i][i] = s[i].size();

    for(int S : rep(1 << n)) if(S) {
        for(int i : rep(n)) if(S & (1 << i)) {
            for(int j : rep(n)) if(!(S & (1 << j))) {
                for(int k : revrep(int(s[i].size()))) {
                    if(s[i].substr(s[i].size() - k, k) == s[j].substr(0, k)) {
                        chmin(dp[S | (1 << j)][j], dp[S][i] + int(s[j].size() - k));
                        break;
                    }
                }
            }
        }
    }

    int ans = 1e9;
    for(int i : rep(n)) chmin(ans, dp[(1 << n) - 1][i]);
    return ans;
}

int main() {
    while(true) {
        int n = in(); if(n == 0) break;
        print(solve(n));
    }
}
accuracy: 1
time_ms: 6670
memory_kb: 4804
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
const int INF = 1<<29;
int n, fnt[15][15];
string s[15];
int memo[1<<15][15];
int dp(int bit, int rht, int cnt){
    if(cnt>=n) return 0;
    if(memo[bit][rht]!=-1) return memo[bit][rht];
    int res = INF;
    for(int i=0;i<n;i++){
        if((bit&1<<i)==0) res = min(res, dp((bit|1<<i), i, cnt+1)+fnt[rht][i]);
    }
    return memo[bit][rht] = res;
}
int main(){
    while(cin >> n, n){
        for(int i=0;i<n;i++) cin >> s[i];
        
        for(int i=0;i<n;i++){
            fnt[n][i] = s[i].size();
            for(int j=0;j<n;j++){
                if(i==j) continue;
                fnt[i][j] = s[j].size();
                for(int k=0;k<s[i].size();k++){
                    int sel = s[i].size()-k;
                    if(s[i].substr(0, k)+s[j].substr(0, sel) == s[i]) fnt[i][j] = min(fnt[i][j], (int)s[j].size()-sel);
                }
            }
        }
        
        int bit=0, cnt=0;
        for(int i=0;i<n;i++){
            bool ok = false;
            for(int j=0;j<n;j++){
                if(i==j) continue;
                if(s[j].find(s[i])!=string::npos) ok = true;
            }
            if(ok){
                bit |= 1<<i;
                cnt++;
            }
        }
        memset(memo, -1, sizeof(memo));
        cout << dp(bit, n, cnt) << endl;
    
    }
    return(0);
}
accuracy: 1
time_ms: 240
memory_kb: 4980
final_rank: 10

code_snippet: // #define _GLIBCXX_DEBUG
#pragma GCC optimize("O2,no-stack-protector,unroll-loops,fast-math")
#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < int(n); i++)
#define per(i, n) for (int i = (n)-1; 0 <= i; i--)
#define rep2(i, l, r) for (int i = (l); i < int(r); i++)
#define per2(i, l, r) for (int i = (r)-1; int(l) <= i; i--)
#define each(e, v) for (auto& e : v)
#define MM << " " <<
#define pb push_back
#define eb emplace_back
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define sz(x) (int)x.size()
template <typename T> void print(const vector<T>& v, T x = 0) {
    int n = v.size();
    for (int i = 0; i < n; i++) cout << v[i] + x << (i == n - 1 ? '\n' : ' ');
    if (v.empty()) cout << '\n';
}
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
template <typename T> bool chmax(T& x, const T& y) {
    return (x < y) ? (x = y, true) : false;
}
template <typename T> bool chmin(T& x, const T& y) {
    return (x > y) ? (x = y, true) : false;
}
template <class T>
using minheap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T> using maxheap = std::priority_queue<T>;
template <typename T> int lb(const vector<T>& v, T x) {
    return lower_bound(begin(v), end(v), x) - begin(v);
}
template <typename T> int ub(const vector<T>& v, T x) {
    return upper_bound(begin(v), end(v), x) - begin(v);
}
template <typename T> void rearrange(vector<T>& v) {
    sort(begin(v), end(v));
    v.erase(unique(begin(v), end(v)), end(v));
}

// __int128_t gcd(__int128_t a, __int128_t b) {
//     if (a == 0)
//         return b;
//     if (b == 0)
//         return a;
//     __int128_t cnt = a % b;
//     while (cnt != 0) {
//         a = b;
//         b = cnt;
//         cnt = a % b;
//     }
//     return b;
// }

struct Union_Find_Tree {
    vector<int> data;
    const int n;
    int cnt;
 
    Union_Find_Tree(int n) : data(n, -1), n(n), cnt(n) {}
 
    int root(int x) {
        if (data[x] < 0) return x;
        return data[x] = root(data[x]);
    }
 
    int operator[](int i) { return root(i); }
 
    bool unite(int x, int y) {
        x = root(x), y = root(y);
        if (x == y) return false;
        if (data[x] > data[y]) swap(x, y);
        data[x] += data[y], data[y] = x;
        cnt--;
        return true;
    }
 
    int size(int x) { return -data[root(x)]; }
 
    int count() { return cnt; };
 
    bool same(int x, int y) { return root(x) == root(y); }
 
    void clear() {
        cnt = n;
        fill(begin(data), end(data), -1);
    }
};

template <int mod> struct Mod_Int {
    int x;

    Mod_Int() : x(0) {}

    Mod_Int(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    static int get_mod() { return mod; }

    Mod_Int& operator+=(const Mod_Int& p) {
        if ((x += p.x) >= mod) x -= mod;
        return *this;
    }

    Mod_Int& operator-=(const Mod_Int& p) {
        if ((x += mod - p.x) >= mod) x -= mod;
        return *this;
    }

    Mod_Int& operator*=(const Mod_Int& p) {
        x = (int)(1LL * x * p.x % mod);
        return *this;
    }

    Mod_Int& operator/=(const Mod_Int& p) {
        *this *= p.inverse();
        return *this;
    }

    Mod_Int& operator++() { return *this += Mod_Int(1); }

    Mod_Int operator++(int) {
        Mod_Int tmp = *this;
        ++*this;
        return tmp;
    }

    Mod_Int& operator--() { return *this -= Mod_Int(1); }

    Mod_Int operator--(int) {
        Mod_Int tmp = *this;
        --*this;
        return tmp;
    }

    Mod_Int operator-() const { return Mod_Int(-x); }

    Mod_Int operator+(const Mod_Int& p) const { return Mod_Int(*this) += p; }

    Mod_Int operator-(const Mod_Int& p) const { return Mod_Int(*this) -= p; }

    Mod_Int operator*(const Mod_Int& p) const { return Mod_Int(*this) *= p; }

    Mod_Int operator/(const Mod_Int& p) const { return Mod_Int(*this) /= p; }

    bool operator==(const Mod_Int& p) const { return x == p.x; }

    bool operator!=(const Mod_Int& p) const { return x != p.x; }

    Mod_Int inverse() const {
        assert(*this != Mod_Int(0));
        return pow(mod - 2);
    }

    Mod_Int pow(long long k) const {
        Mod_Int now = *this, ret = 1;
        for (; k > 0; k >>= 1, now *= now) {
            if (k & 1) ret *= now;
        }
        return ret;
    }

    friend ostream& operator<<(ostream& os, const Mod_Int& p) {
        return os << p.x;
    }

    friend istream& operator>>(istream& is, Mod_Int& p) {
        long long a;
        is >> a;
        p = Mod_Int<mod>(a);
        return is;
    }
};

ll mpow2(ll x, ll n, ll mod) {
    ll ans = 1;
    x %= mod;
    while (n != 0) {
        if (n & 1) ans = ans * x % mod;
        x = x * x % mod;
        n = n >> 1;
    }
    ans %= mod;
    return ans;
}

template <typename T> T modinv(T a, const T& m) {
    T b = m, u = 1, v = 0;
    while (b > 0) {
        T t = a / b;
        swap(a -= t * b, b);
        swap(u -= t * v, v);
    }
    return u >= 0 ? u % m : (m - (-u) % m) % m;
}

ll divide_int(ll a, ll b) {
    if (b < 0) a = -a, b = -b;
    return (a >= 0 ? a / b : (a - b + 1) / b);
}

// const int MOD = 1000000007;
const int MOD = 998244353;
using mint = Mod_Int<MOD>;

// ----- library -------
// ----- library -------

int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (1) {
        int n;
        cin >> n;
        if (!n)
            break;
        vector<string> s(n);
        rep(i, n) cin >> s[i];
        vector<vector<int>> c(n, vector<int>(n));
        rep(i, n) rep(j, n) {
            int li = sz(s[i]), lj = sz(s[j]);
            c[i][j] = lj;
            rep(k, li) {
                bool ok = true;
                int val = lj;
                rep(l, min(lj, li - k)) {
                    if (s[i][k + l] != s[j][l]) {
                        ok = false;
                        break;
                    }
                    val--;
                }
                if (ok)
                    chmin(c[i][j], val);
            }
        }
        vector<vector<int>> dp(1 << n, vector<int>(n, 1e9));
        rep(i, n) dp[1 << i][i] = sz(s[i]);
        rep(t, 1 << n) rep(i, n) rep(j, n) {
            if (t >> j & 1)
                continue;
            chmin(dp[t | (1 << j)][c[i][j] == 0 ? i : j], dp[t][i] + c[i][j]);
        }
        cout << *min_element(all(dp[(1 << n) - 1])) << '\n';
    }
}
accuracy: 1
time_ms: 350
memory_kb: 4748
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

int calc_extra(const string& S, const string& T) {
	int ans = T.size();
	for (int i = 1; i <= S.size() && i <= T.size(); i++) {
		if (S.substr(S.size() - i) == T.substr(0, i)) {
			ans = T.size() - i;
		}
	}
	return ans;
}

int solve_sequence(int N, const vector<string>& S) {
	vector<vector<int> > extras(N, vector<int>(N));
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			extras[i][j] = calc_extra(S[i], S[j]);
		}
	}
	vector<vector<int> > dp(1 << N, vector<int>(N, INF));
	for (int i = 0; i < N; i++) {
		dp[1 << i][i] = S[i].size();
	}
	for (int i = 1; i < (1 << N); i++) {
		if ((i & (i - 1)) == 0) {
			continue; // i = 2^k
		}
		for (int j = 0; j < N; j++) {
			if ((i >> j) & 1) {
				int sub = i - (1 << j);
				for (int k = 0; k < N; k++) {
					if ((sub >> k) & 1) {
						dp[i][j] = min(dp[i][j], dp[sub][k] + extras[k][j]);
					}
				}
			}
		}
	}
	int ans = *min_element(dp[(1 << N) - 1].begin(), dp[(1 << N) - 1].end());
	return ans;
}

int solve(int N, const vector<string>& S) {
	vector<string> T;
	for (int i = 0; i < N; i++) {
		bool flag = true;
		for (int j = 0; j < N; j++) {
			if ((S[j] == S[i] && j < i) || (S[j] != S[i] && S[j].find(S[i]) != string::npos)) {
				flag = false;
			}
		}
		if (flag) {
			T.push_back(S[i]);
		}
	}
	return solve_sequence(T.size(), T);
}

int main() {
	while (true) {
		int N;
		cin >> N;
		if (N == 0) {
			break;
		}
		vector<string> S(N);
		for (int i = 0; i < N; i++) {
			cin >> S[i];
		}
		int ans = solve(N, S);
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 4528
final_rank: 3

code_snippet: // I SELL YOU...! 
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<queue>
#include<chrono>
#include<iomanip>
#include<map>
#include<set>
#include<bitset>
using namespace std;
using ll = long long;
using P = pair<ll,ll>;
using TP = tuple<ll,ll,ll>;
void init_io(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(18);
}
const ll INF = 1e15;
ll calc_dp(ll s, ll i, const vector<vector<ll>> &pat, vector<vector<ll>> &dp) {
  ll n = pat.size();
  ll k = 0;
  if (dp[s][i] != -1) return dp[s][i];
  for (int i=0;i<n;i++) {
    if ((1ll << i) & s) k++;
  }
  if (k==1) {
    return dp[s][i] = pat[i][i];
  }
  ll prev_s = s ^ (1ll << i);
  ll res = INF;
  for (int j=0;j<n;j++) {
    if (i==j || ((prev_s & (1ll << j)) == 0)) continue;
    res = min(res, calc_dp(prev_s, j, pat, dp) + pat[i][i] - pat[j][i]);
  }
  // cout << bitset<14>(s) <<" "<<i <<" "<<res << endl;
  return dp[s][i] = res;
};

ll max_match(const string &s, const string &t) {
  ll n = s.size(), m = t.size();
  ll res = 0;
  for (int i=1;i<=min(n, m);i++) {
    bool can = true;
    for (int j=0;j<i;j++) {
      if (s[(n-i)+j] != t[j]) {
        can = false;
        break;
      }
    }
    if (can) {
      res = i;
    }
  }
  return res;
};
void solve() {
  ll n;
  cin >> n;
  if (n==0) return;
  vector<string> s(n);
  for(int i=0;i<n;i++) {
    cin >> s[i];
  }
  for (auto itr=s.begin();itr!=s.end();) {
    ll c = 0;
    for (auto t: s) {
      if (t == *itr) {
        if (c==0) {
          c++;
          continue;
        }
      }
      if (t.find(*itr) != string::npos) {
        c = -1;
        break;
      }
    }
    if (c==-1) {
      itr = s.erase(itr);
    } else {
      itr++;
    }
  }
  n = s.size();
  vector<vector<ll>> dp((1ll<<n), vector<ll>(n, -1));
  vector<vector<ll>> pat(n, vector<ll>(n, 0));
  for (int i=0;i<n;i++) {
    for (int j=0;j<n;j++) {
      if (i==j) {
        pat[i][i] = s[i].size();
      } else {
        pat[i][j] = max_match(s[i], s[j]);
      }
    }
  }
  ll ans = 1e15;
  for (int i=0;i<n;i++) {
    ans = min(ans, calc_dp((1ll<<n) -1, i,pat, dp));
  }
  cout << ans << endl;
  solve();
}
signed main(){
  init_io();
  solve();
}
accuracy: 1
time_ms: 320
memory_kb: 101052
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#include <chrono>
#include <thread>
////#include <atcoder/all>

//using namespace atcoder;
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vb = vector<bool>;
using vvb = vector<vb>;
using vvvb = vector<vvb>;
using vd = vector<double>;
using vvd = vector<vd>;
using vvvd = vector<vvd>;
#define all(A) A.begin(),A.end()
#define ALL(A) A.begin(),A.end()
#define rep(i, n) for (ll i = 0; i < (ll) (n); i++)
using pqr = priority_queue<pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>>;

template<class T>
bool chmax(T& p, T q) {
    if (p < q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}
template<class T>
bool chmin(T& p, T q) {
    if (p > q) {
        p = q;
        return 1;
    }
    else {
        return 0;
    }
}

ll gcd(ll(a), ll(b)) {
    if (b == 0)return a;
    ll c = a;
    while (a % b != 0) {
        c = a % b;
        a = b;
        b = c;
    }
    return b;
}

ll Eulers_phi(ll n) {
    ll res = 0;
    ll N = n;
    vll P;
    for (ll p = 2; p * p <= N; p++) {
        if (N % p == 0) {
            P.push_back(p);
            while (N % p == 0)N /= p;
        }
    }
    if (N != 1)P.push_back(N);

    N = P.size();
    rep(bit, (1 << N)) {
        ll k = 1;
        ll t = 0;
        rep(i, N) {
            if (bit & (1 << i)) {
                k *= P[i];
                t++;
            }
        }
        res += (t % 2 == 0 ? 1 : -1) * n / k;
    }
    return res;

}

map<string, ll> M;

bool OK = 1;
ll dfs(string S) {
    ll res = 0;
    ll N = S.size();
    rep(i, N) {
        ll d = 0;
        ll R = i;
        if (S[i] <= 'Z' && S[i] >= 'A') {
            string G = "";
            if (S.size() > 1 && (S[i + 1] <= 'z' && S[i + 1] > 'a')) {
                G = S.substr(i, 2);
                R = i + 1;
            }
            else {
                G = S.substr(i, 1);
                R = i;
            }
            if (!M.count(G)) {
                OK = 0;
                return res;
            }
            d = M[G];
        }
        else if (S[i] == '(') {
            ll L = i;
            ll k = 0;
            for (ll j = i; j < N; j++) {
                if (S[j] == '(')k++;
                else if (S[j] == ')') {
                    k--;
                    if (k == 0) {
                        d = dfs(S.substr(L + 1, j - L - 1));
                        R = j;
                        break;
                    }
                }
            }
        }
        else continue;
        ll b = 1;
        if (S.size() > R + 1) {
            if ('0' <= S[R + 1] && S[R + 1] <= '9') {
                b = S[R + 1] - '0';
                R++;
                if (S.size() > R + 1) {
                    if ('0' <= S[R + 1] && S[R + 1] <= '9') {
                        b = b * 10 + S[R + 1] - '0';
                        R++;
                    }
                }
            }
        }
        res += d * b;
        i = R;
    }


    return res;
}


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


    while (1) {
        ll N;
        cin >> N;
        if (N == 0)return 0;
        vector<string> S(N);
        rep(i, N)cin >> S[i];
        vector<bool> D(N, 1);
        rep(i, N) {
            rep(j, N) {
                if (i == j)continue;
                for (ll k = 0; k < ll(S[j].size()) - ll(S[i].size())+1; k++) {
                    if (S[j].substr(k, S[i].size()) == S[i]) {
                        D[i] = 0;
                    }
                }
            }
        }
        vector<string> T;
        rep(i, N) {
            if (D[i])T.push_back(S[i]);
        }
        N = T.size();
        S = T;
        vvll DP((1 << N), vll(N, 1e18));
        rep(i, N) {
            DP[(1 << i)][i] = T[i].size();
        }

        vvll Z(N, vll(N,0));
        rep(i, N)rep(j, N) {
            rep(k, S[j].size()) {
                if (k == 0)continue;
                if (S[i].size()<k)break;
                string P = S[i].substr(S[i].size() - k, k);
                string Q = S[j].substr(0, k);
                if (P == Q) {
                    Z[i][j] = k;
                }
            }
        }
        rep(bit, (1 << N)) {
            if (bit == 0)continue;
            rep(j, N) {
                if (!(bit & (1 << j)))continue;
                rep(n, N) {
                    if (bit & (1 << n))continue;
                    chmin(DP[bit + (1 << n)][n], DP[bit][j]+ll(T[n].size()) - Z[j][n]);
                }
            }
        }
        ll an = 1e18;
        rep(i, N)chmin(an, DP[(1 << N) - 1][i]);
        cout << an << endl;
    }

}
accuracy: 1
time_ms: 180
memory_kb: 5812
final_rank: 9

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <climits>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

/* macro */

#define rep(i, a, n) for (int i = (int)(a); i < (int)(n); i++)
#define rrep(i, a, n) for (int i = ((int)(n - 1)); i >= (int)(a); i--)
#define Rep(i, a, n) for (i64 i = (i64)(a); i < (i64)(n); i++)
#define RRep(i, a, n) for (i64 i = ((i64)(n - i64(1))); i >= (i64)(a); i--)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define Bit(n) (1LL << (n))

/* macro end */

/* template */

namespace ebi {

#ifdef LOCAL
#define debug(...)                                                      \
    std::cerr << "LINE: " << __LINE__ << "  [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)
#else
#define debug(...)
#endif

void debug_out() { std::cerr << std::endl; }

template <typename Head, typename... Tail>
void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cout << " :";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

template <typename T1, typename T2>
std::istream &operator>>(std::istream &os, std::pair<T1, T2> &pa) {
    return os >> pa.first >> pa.second;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec) {
    for (std::size_t i = 0; i < vec.size(); i++)
        os << vec[i] << (i + 1 == vec.size() ? "" : " ");
    return os;
}

template <typename T>
std::istream &operator>>(std::istream &os, std::vector<T> &vec) {
    for (T &e : vec) std::cin >> e;
    return os;
}

template <typename T>
std::ostream &operator<<(std::ostream &os, const std::optional<T> &opt) {
    if (opt) {
        os << opt.value();
    } else {
        os << "invalid value";
    }
    return os;
}

using std::size_t;
using i32 = std::int32_t;
using u32 = std::uint32_t;
using i64 = std::int64_t;
using u64 = std::uint64_t;

template <class T, T init>
auto make_vector(int n) {
    return std::vector<T>(n, init);
}

template <class T, T init, typename Head, typename... Tail>
auto make_vector(Head n, Tail... ts) {
    return std::vector(n, make_vector<T, init>(ts...));
}

template <class T>
inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T pow(T x, i64 n) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = res * x;
        x = x * x;
        n >>= 1;
    }
    return res;
}

template <class T>
T mod_pow(T x, i64 n, i64 mod) {
    T res = 1;
    while (n > 0) {
        if (n & 1) res = (res * x) % mod;
        x = (x * x) % mod;
        n >>= 1;
    }
    return res;
}

template <class T>
T scan() {
    T val;
    std::cin >> val;
    return val;
}

template <class T>
struct Edge {
    int to;
    T cost;
    Edge(int _to, T _cost = 1) : to(_to), cost(_cost) {}
};

template <class T>
struct Graph : std::vector<std::vector<Edge<T>>> {
    using std::vector<std::vector<Edge<T>>>::vector;
    void add_edge(int u, int v, T w, bool directed = false) {
        (*this)[u].emplace_back(v, w);
        if (directed) return;
        (*this)[v].emplace_back(u, w);
    }
};

struct graph : std::vector<std::vector<int>> {
    using std::vector<std::vector<int>>::vector;
    void add_edge(int u, int v, bool directed = false) {
        (*this)[u].emplace_back(v);
        if (directed) return;
        (*this)[v].emplace_back(u);
    }
};

constexpr i64 LNF = std::numeric_limits<i64>::max() / 4;

constexpr int INF = std::numeric_limits<int>::max() / 2;

const std::vector<int> dy = {1, 0, -1, 0, 1, 1, -1, -1};
const std::vector<int> dx = {0, 1, 0, -1, 1, -1, 1, -1};

}  // namespace ebi

namespace ebi {

void main_() {
    int n;
    while (std::cin >> n, n != 0) {
        std::vector<std::string> s(n);
        std::cin >> s;
        {
            std::vector<std::string> cp;
            rep(i, 0, n) {
                bool flag = false;
                rep(j, 0, n) {
                    if (flag) break;
                    if (i == j) continue;
                    int isz = s[i].size();
                    int jsz = s[j].size();
                    if (isz >= jsz) continue;
                    rep(k, 0, jsz) {
                        if (k + isz > jsz) break;
                        if (s[j].substr(k, isz) == s[i]) {
                            flag = true;
                            break;
                        }
                    }
                }
                if (flag) continue;
                cp.emplace_back(s[i]);
            }
            s = cp;
        }
        n = s.size();
        std::vector dp(1 << n, std::vector<int>(n, INF));
        std::vector duplicates(n, std::vector<int>(n, 0));
        rep(i,0,n) rep(j,0,n) {
            int isz = s[i].size();
            int jsz = s[j].size();
            rep(k,0,isz) {
                bool flag = true;
                rep(l,0,isz-k) {
                    if(l >= jsz || s[i][k+l] != s[j][l]) {
                        flag = false;
                        break;
                    }
                }
                if(flag) {
                    duplicates[i][j] = isz - k;
                    break;
                }
            }
        }
        auto f = [&](auto &&self, int bit, int back) -> int {
            if(dp[bit][back] != INF) return dp[bit][back];
            if(bit == (1<<back)) return dp[bit][back] = s[back].size();
            int prev = bit ^ (1<<back);
            rep(i,0,n) if((prev >> i) & 1) {
                chmin(dp[bit][back], self(self, prev, i) + (int)s[back].size() - duplicates[i][back]);
            }
            return dp[bit][back];
        };
        int ans = INF;
        rep(i, 0, n) chmin(ans, f(f, (1 << n) - 1, i));
        std::cout << ans << '\n';
    }
}

}  // namespace ebi

int main() {
    std::cout << std::fixed << std::setprecision(15);
    std::cin.tie(nullptr);
    std::ios::sync_with_stdio(false);
    int t = 1;
    // std::cin >> t;
    while (t--) {
        ebi::main_();
    }
    return 0;
}
accuracy: 1
time_ms: 260
memory_kb: 4792
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
template <class T> using V = vector<T>;

int solve2(V<string>& T) {
    const int INF = 1 << 30;
    int N = T.size();
    int N2 = 1 << N;
    V<V<int>> cost(N, V<int>(N, INF));
    rep(las, N) {
        rep(nex, N) {
            if (las == nex) continue;
            int l2 = T[nex].size();
            for (int sz = l2 - 1; sz >= 0; sz--) {
                // S[nex].substr(0, sz)
                if (T[las].size() < sz) continue;
                if (T[las].substr(T[las].size() - sz) == T[nex].substr(0, sz)) {
                    cost[las][nex] = l2 - sz;
                    break;
                }
            }
        }
    }
    V<V<int>> dp(N2, V<int>(N, INF));
    rep(i, N) dp[1 << i][i] = T[i].size();
    for (int s = 1; s < N2; s++) {
        for (int las = 0; las < N; las++) {
            if ((s >> las & 1) == 0) continue;
            if (dp[s][las] == INF) continue;
            for (int nex = 0; nex < N; nex++) {
                if (s >> nex & 1) continue;
                dp[s | (1 << nex)][nex] = min(dp[s | (1 << nex)][nex], dp[s][las] + cost[las][nex]);
            }
        }
    }
    int ans = *min_element(dp[N2 - 1].begin(), dp[N2 - 1].end());
    return ans;
}

void solve(int N) {
    V<string> S(N);
    rep(i, N) cin >> S[i];
    V<int> cont(N, 0);
    rep(i, N) {
        // check S[i] in S[j]
        int lsi = S[i].size();
        rep(j, N) {
            if (i == j) continue;
            int lsj = S[j].size();
            if (lsi > lsj) continue;
            rep(k, lsj - lsi + 1) {
                if (S[i] == S[j].substr(k, lsi)) {
                    cont[i] = 1;
                    break;
                }
            }
            if (cont[i]) break;
        }
    }
    V<string> T;
    rep(i, N) if (cont[i] == 0) T.push_back(S[i]);
    cout << solve2(T) << '\n';
    return;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N;
    while (cin >> N, N != 0) solve(N);
    return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 4572
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

#ifdef _RUTHEN
#include "debug.hpp"
#else
#define show(...) true
#endif

using ll = long long;
#define rep(i, n) for (int i = 0; i < (n); i++)
template <class T> using V = vector<T>;

int solve2(V<string>& T) {
    const int INF = 1 << 30;
    int N = T.size();
    int N2 = 1 << N;
    V<V<int>> dp(N2, V<int>(N, INF));
    rep(i, N) dp[1 << i][i] = T[i].size();
    for (int s = 1; s < N2; s++) {
        for (int las = 0; las < N; las++) {
            if ((s >> las & 1) == 0) continue;
            if (dp[s][las] == INF) continue;
            for (int nex = 0; nex < N; nex++) {
                if (s >> nex & 1) continue;
                int l2 = T[nex].size();
                for (int sz = l2 - 1; sz >= 0; sz--) {
                    // S[nex].substr(0, sz)
                    if (T[las].size() < sz) continue;
                    if (T[las].substr(T[las].size() - sz) == T[nex].substr(0, sz)) {
                        dp[s | (1 << nex)][nex] = min(dp[s | (1 << nex)][nex], dp[s][las] + l2 - sz);
                        break;
                    }
                }
            }
        }
    }
    int ans = *min_element(dp[N2 - 1].begin(), dp[N2 - 1].end());
    return ans;
}

void solve(int N) {
    V<string> S(N);
    rep(i, N) cin >> S[i];
    V<int> cont(N, 0);
    rep(i, N) {
        // check S[i] in S[j]
        int lsi = S[i].size();
        rep(j, N) {
            if (i == j) continue;
            int lsj = S[j].size();
            if (lsi > lsj) continue;
            rep(k, lsj - lsi + 1) {
                if (S[i] == S[j].substr(k, lsi)) {
                    cont[i] = 1;
                    break;
                }
            }
            if (cont[i]) break;
        }
    }
    show(cont);
    V<string> T;
    rep(i, N) if (cont[i] == 0) T.push_back(S[i]);
    cout << solve2(T) << '\n';
    return;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N;
    while (cin >> N, N != 0) solve(N);
    return 0;
}
accuracy: 1
time_ms: 6730
memory_kb: 4676
final_rank: 19

code_snippet: #include<bits/stdc++.h>
using namespace std;

int main(void){
    while(1){
        int n;
        cin >> n;
        if(n == 0) break;
        vector<string> S(n);
        for(int i = 0; i < n; i++) cin >> S[i];
        vector<string> T;
        for(int i = 0; i < n; i++){
            bool ok = true;
            for(int j = 0; j < n; j++){
                if(i == j) continue;
                int found = S[j].find(S[i]);
                if(found != string::npos){
                    ok = false;
                    break;
                }
            }
            if(ok) T.push_back(S[i]);
        }
        S = T;
        n = S.size();
        vector<vector<int>> common(n, vector<int>(n, 0));
        for(int i = 0; i < n; i++){
            for(int j = 0; j < n; j++){
                if(i == j) continue;
                int li = S[i].size();
                int lj = S[j].size();
                int mi = min(li, lj);
                for(int k = 1; k < mi; k++){
                    bool ok = true;
                    for(int l = 0; l < k; l++){
                        if(S[i][li - k + l] != S[j][l]){
                            ok = false;
                            break;
                        }
                    }
                    if(ok) common[i][j] = k;
                }
            }
        }
        vector<vector<int>> dp(1 << n, vector<int>(n, 0));
        for(int bit = 0; bit < (1 << n); bit++){
            for(int j = 0; j < n; j++){
                if(bit >> j & 1){
                    for(int k = 0; k < n; k++){
                        if(j != k && (bit >> k & 1)){
                            dp[bit][j] = max(dp[bit][j], dp[bit ^ (1 << j)][k] + common[j][k]);
                        }
                    }
                }
            }
        }
        int ans = 0;
        for(auto s: S) ans += s.size();
        int max_ = 0;
        for(int i = 0; i < n; i++) max_ = max(max_, dp[(1 << n) - 1][i]);
        cout << ans - max_ << "\n";
        
        
    }
}
accuracy: 1
time_ms: 210
memory_kb: 4764
final_rank: 8

code_snippet: #define rep(i, n) for(int i=0; i<(n); ++i)
#define rrep(i, n) for(int i=(n-1); i>=0; --i)
#define rep2(i, s, n) for(int i=s; i<(n); ++i)
#define ALL(v) (v).begin(), (v).end()
#define memr(dp, val) memset(dp, val, sizeof(dp))
#define fi first
#define se second
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#include <bits/stdc++.h>
using namespace std;
template<typename T>
using min_priority_queue = priority_queue<T, vector<T>, greater<T> >;
typedef long long ll;
const int INTINF = INT_MAX >> 1;
static const ll LLINF = (LLONG_MAX >> 1);

int n;
string s[15];
string ss[15]; // 包含しているsを除いた入力
int dp[1 << 15][15][15];

bool a_has_b(string a, string b){
	if(a.size() < b.size()) return false;

	rep(i, a.size()){
		if(i + b.size() - 1 >= a.size()) break;
		bool ok = true;
		rep(j, b.size()){
			if(a[i+j] != b[j]) ok = false;
		}
		if(ok) return true;
	}
	return false;
}

bool input(){

	cin >> n;
	if(!n) return false;
	rep(i, n) cin >> s[i];

	bool inclusions[15];
	memr(inclusions, 0);
	rep(i, n){
		rep2(j, i+1, n){
			if(a_has_b(s[i], s[j])) inclusions[j] = true; 
			if(a_has_b(s[j], s[i])) inclusions[i] = true; 
		}
	}

	ss[0] = "";
	int cnt = 1;
	rep(i, n){
		if(!inclusions[i]){
			ss[cnt] = s[i];
			cnt++;
		}
	}

	n = cnt - 1;

	return true;
}

int cost[15][15];

int calc(string a, string b){
	int ret = 0;
	rep(i, a.size()){
		int cnt = 0;
		rep(j, b.size()){
			if(i + j >= a.size()) break;
			if(a[i+j] == b[j]) {
				cnt++;
			}
			else{
				cnt = 0;
				break;
			}
		}
		chmax(ret, cnt);
	}
	return ret;
}

int main(){
    std::cout << std::fixed << std::setprecision(15);

	while(input()){
		rep(i, 1 << n) rep(j, 15) rep(k, 15) dp[i][j][k] = INTINF;

		rep(i, 15) rep(j, 15) cost[i][j] = INTINF;
		rep(i, n+1){
			rep(j, n+1){
				chmin(cost[i][j], calc(ss[i], ss[j]));
				chmin(cost[j][i], calc(ss[j], ss[i]));
			}
		}
		
		queue<tuple<int, int, int> > q;
		q.push({0, 0, 0});
		dp[0][0][0] = 0;

		while(q.size()){
			int S, front, back;
			auto f = q.front(); q.pop();
			tie(S, front, back) = f;
			rep(i, n){
				if(!(S >> i & 1)){
					if(dp[S | 1 << i][i+1][back] == INTINF) q.push({S | 1 << i, i + 1, back});
					if(dp[S | 1 << i][front][i+1] == INTINF) q.push({S | 1 << i, front, i + 1});
					chmin(dp[S | 1 << i][i+1][back], dp[S][front][back] + int(ss[i+1].size()) - cost[i+1][front]);
					chmin(dp[S | 1 << i][front][i+1], dp[S][front][back] + int(ss[i+1].size()) - cost[back][i+1]);
				}
			}
		}

		int ans = INTINF;
		rep(i, n+1) rep(j, n+1) {
			chmin(ans, dp[(1 << n) - 1][i][j]);
		}
		cout << ans << endl;
	}
    return 0;
}
accuracy: 1
time_ms: 2380
memory_kb: 22356
final_rank: 16

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;i++)
#define cinf(n,x) for(int i=0;i<(n);i++)cin>>x[i];
#define ft first
#define sc second
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(),(v).end()
#define LB(a,x) lb(all(a),x)-a.begin()
#define UB(a,x) ub(all(a),x)-a.begin()
#define mod 1000000007
//#define mod 998244353
#define FS fixed<<setprecision(15)
using namespace std;
typedef long long ll;
const double pi=3.141592653589793;
template<class T> using V=vector<T>;
using P=pair<int,int>;
typedef unsigned long long ull;
typedef long double ldouble;
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline void out(T a){ cout << a << '\n'; }
void YN(bool ok){if(ok) cout << "Yes" << endl; else cout << "No" << endl;}
//void YN(bool ok){if(ok) cout << "YES" << endl; else cout << "NO" << endl;}


const ll INF=1e18;
const int mx=200005;

int dp[(1<<14)+10][20];

int main(){
    //オーバーフローは大丈夫ですか？？
    cin.tie(0);ios::sync_with_stdio(false);
    int cnt=0;
    while(true){
        cnt++;
        int n;
        cin>>n;
        if(n==0) break;
        V<string> s(n);
        cinf(n,s);
        
        int MX=1000000;
        V<int> lst((1<<n),-1);
        V<V<int>> cost(n,V<int>(n,MX));
        rep(i,n){
            int bit=(1<<i);
            for(int j=0;j<n;j++){
                if(j==i) continue;
                bool ok=0;
                rep(L,s[i].size()){
                    for(int R=L;R<s[i].size();R++){
                        if(s[i].substr(L,R-L+1)==s[j]){
                            ok=1;
                        }
                    }
                }
                if(ok) cost[i][j]=0;
            }
            
        }
        rep(i,n){
            rep(j,n){
                if(i==j) cost[i][j]=0;
                else{
                    chmin(cost[i][j],(int)s[j].size());
                    rep(k,s[i].size()){
                        int len=s[i].size()-k;
                        if(len>s[j].size()) continue;
                        if(s[i].substr(k,len)==s[j].substr(0,len)){
                            chmin(cost[i][j],(int)s[j].size()-len);
                        }
                    }
                }
            }
        }
        rep(i,(1<<n))rep(j,n)dp[i][j]=MX;
        rep(i,n){
            dp[(1<<i)][i]=s[i].size();
        }
        rep(i,(1<<n)){
            rep(j,n){
                if(dp[i][j]==MX||!(i>>j&1)) continue;
                rep(k,n){
                    if(i>>k&1) continue;
                    int to=i|(1<<k);
                    
                    if(cost[j][k]==0) chmin(dp[to][j],dp[i][j]);
                    else chmin(dp[to][k],dp[i][j]+cost[j][k]);
                }
            }
        }
        int ans=MX;
        rep(i,n) chmin(ans,dp[(1<<n)-1][i]);
        out(ans);
    }
}
accuracy: 1
time_ms: 310
memory_kb: 4792
final_rank: 13

code_snippet: // #include "atcoder/all"
#include <iostream> // cout, endl, cin
#include <string> // string, to_string, stoi
#include <vector> // vector
#include <algorithm> // min, max, swap, sort, reverse, lower_bound, upper_bound
#include <utility> // pair, make_pair
#include <tuple> // tuple, make_tuple
#include <cstdint> // int64_t, int*_t
#include <cstdio> // printf
#include <map> // map
#include <queue> // queue, priority_queue
#include <set> // set
#include <stack> // stack
#include <deque> // deque
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <bitset> // bitset
#include <cctype> // isupper, islower, isdigit, toupper, tolower
#include <iomanip> // setprecision
#include <complex> // complex
#include <math.h>
#include <functional>
#include <cassert>
using namespace std;
// using namespace atcoder;
using ll = long long;
using P = pair<ll,ll>;
constexpr ll INF = 1e15;
constexpr ll LLMAX = 9223372036854775807;
constexpr int inf = 1e9;
// constexpr ll mod = 1000000007;
constexpr ll mod = 998244353;
// 右下左上
const int dx[8] = {1, 0, -1, 0,1,1,-1,-1};
const int dy[8] = {0, 1, 0, -1,1,-1,1,-1};
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
#define eol "\n"
// ---------------------------------------------------------------------------

bool solve(){
  int N;
  cin >> N;
  if(N == 0) return false;
  vector<string> S(N);
  for(int i=0; i<N; i++){
    cin >> S[i];
  }
  vector<int> lost(N,false);
  for(int i=0; i<N; i++){
    for(int j=0; j<N; j++){
      if(i == j) continue;
      for(int l=0; l<S[j].size(); l++){
        if(l+S[i].size() > S[j].size()) continue;
        if(S[i] == S[j].substr(l,S[i].size())){
          lost[i] = true;
        }
      }
    }
  }
  int cnt = 0;
  map<int,int> pos;
  for(int i=0; i<N; i++){
    if(lost[i]) continue;
    pos[cnt] = i;
    cnt++;
  }
  vector<vector<int>> dist(cnt,vector<int>(cnt));
  for(int i=0; i<cnt; i++){
    for(int j=0; j<cnt; j++){
      string s = S[pos[i]];
      string t = S[pos[j]];
      int mx = 0;
      for(int l=0; l<s.size(); l++){
        int len = s.size()-l;
        if(s.substr(l) == t.substr(0,len)){
          mx = len;
          break;
        }
      }
      dist[i][j] = t.size()-mx;
    }
  }
  vector<vector<int>> dp(cnt,vector<int>((1LL<<cnt),inf));
  for(int i=0; i<cnt; i++){
    dp[i][(1LL<<i)] = S[pos[i]].size();
  }
  for(int bit=0; bit<(1LL<<cnt); bit++){
    for(int i=0; i<cnt; i++){
      if(!(bit & (1LL<<i))) continue;
      for(int nxt=0; nxt<cnt; nxt++){
        if(bit & (1LL<<nxt)) continue;
        if(chmin(dp[nxt][bit+(1LL<<nxt)],dp[i][bit]+dist[i][nxt]));
      }
    }
  }
  int ans = inf;
  for(int i=0; i<cnt; i++){
    chmin(ans, dp[i][(1LL<<cnt)-1]);
  }
  // for(int i=0; i<cnt; i++){
  //   for(int j=0; j<cnt ;j++){
  //     cout << dist[i][j] << " \n"[j+1==cnt];
  //   }
  // }
  cout << ans << endl;
  return true;
}

int main(){
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  while(solve());
  return 0;
}
accuracy: 1
time_ms: 160
memory_kb: 4140
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main() {
    while (true) {
        int n;
        cin >> n;
        if(n == 0) {
            return 0;
        }
        vector<string>S(n);
        for(int i = 0; i < n; i++) {
            cin >> S[i];
        }
        vector<string>T;
        for(int i = 0; i < n; i++) {
            bool flag = true;
            for(int j = 0; j < n; j++) {
                if(i == j || S[i].size() >= S[j].size()) {
                    continue;
                }
                for(int k = 0; k < S[j].size()-S[i].size()+1; k++) {
                    if(S[i] == S[j].substr(k,S[i].size())) {
                        flag = false;
                    }
                }
            }
            if(flag) {
                T.push_back(S[i]);
            }
        }
        vector<vector<int>>tmp(T.size(),vector<int>(T.size()));
        vector<vector<int>>dp(1 << T.size(),vector<int>(T.size(),1001001001));
        for(int i = 0; i < T.size(); i++) {
            dp[(1 << i)][i] = T[i].size();
            for(int j = 0; j < T.size(); j++) {
                for(int k = 0; k < min(T[i].size(),T[j].size()); k++) {
                    if(T[i].substr(T[i].size()-k,k) == T[j].substr(0,k)) {
                        tmp[i][j] = T[j].size()-k;
                    }
                }
            }
        }
        for(int i = 0; i < (1 << T.size()); i++) {
            for(int j = 0; j < T.size(); j++) {
                for(int k = 0; k < T.size(); k++) {
                    if(!(1 & (i >> k))) {
                        dp[i|(1 << k)][k] = min(dp[i|(1 << k)][k],dp[i][j]+tmp[j][k]);
                    }
                }
            }
        }
        cout << *min_element(dp[(1 << T.size())-1].begin(),dp[(1 << T.size())-1].end()) << endl;
    }
}
accuracy: 1
time_ms: 180
memory_kb: 4848
final_rank: 6