#include <bits/stdc++.h>
using namespace std;
using lint = long long;
template<class T = int> using V = vector<T>;
template<class T = int> using VV = V< V<T> >;

template<class T> struct PrimalDual {
    struct Edge { int to, rev; T cap, cost; };
    const T inf = numeric_limits<T>::max();
    const int n;
    VV<Edge> g;
    V<T> pot, dist;
    V<> pv, pe;
    PrimalDual(int n) : n(n), g(n), pot(n), dist(n), pv(n), pe(n) {}
    void add_edge(int from, int to, T cap, T cost) {
        assert(from != to);
        assert(cap >= 0);
        if (!cap) return;
        assert(cost >= 0);
        g[from].emplace_back(Edge{to, (int)g[to].size(), cap, cost});
        g[to].emplace_back(Edge{from, (int)g[from].size() - 1, 0, -cost});
    }
    void dijkstra(int s) {
        using P = pair<T, int>;
        priority_queue< P, V<P>, greater<P> > pque;
        fill(begin(dist), end(dist), inf);
        pque.emplace(dist[s] = 0, s);
        while (!pque.empty()) {
            T d; int v;
            tie(d, v) = pque.top(); pque.pop();
            if (d > dist[v]) continue;
            for (int i = 0; i < (int)g[v].size(); ++i) {
                const Edge& e = g[v][i];
                if (!e.cap or dist[e.to] <= dist[v] + e.cost - (pot[e.to] - pot[v])) continue;
                pv[e.to] = v, pe[e.to] = i;
                pque.emplace(dist[e.to] = dist[v] + e.cost - (pot[e.to] - pot[v]), e.to);
            }
        }
    }
    T min_cost_flow(int s, int t, T f) {
        assert(s != t);
        assert(f >= 0);
        T res = 0;
        fill(begin(pot), end(pot), 0);
        while (f > 0) {
            dijkstra(s);
            if (dist[t] == inf) return -1;
            for (int v = 0; v < n; ++v) pot[v] += dist[v];
            T d = f;
            for (int v = t; v != s; v = pv[v]) {
                d = min(d, g[pv[v]][pe[v]].cap);
            }
            f -= d;
            res += d * pot[t];
            for (int v = t; v != s; v = pv[v]) {
                Edge& e = g[pv[v]][pe[v]];
                e.cap -= d;
                g[v][e.rev].cap += d;
            }
        }
        return res;
    }
};

int N;
vector<string> S;

bool contain(string S, string T) {
    //cerr << S << " " << T << endl;
    string U = S + T;
    vector<int> A(U.size());
    A[0] = U.size();
    int i = 1;
    int j = 0;
    while(i < U.size()) {
        while(i + j < U.size() && U[j] == U[i+j]) ++j;
        A[i] = j;
        if(j == 0) {
            ++i;
            continue;
        }
        int k = 1;
        while(i + k < U.size() && k + A[k] < j) A[i+k] = A[k], k++;
        i += k;
        j -= k;
    }
    //cerr << S << " " << T << endl;
    //for(int i = 0; i < A.size(); i++) cerr << A[i] << " ";
    //cerr << endl;
    for(int i = S.size() + 1; i < U.size(); i++) {
        if(A[i] >= S.size()) return true;
    }
    return false;
}

int connect(string T, string S) {
    string U = S + T;
    vector<int> A(U.size());
    A[0] = U.size();
    int i = 1;
    int j = 0;
    while(i < U.size()) {
        while(i + j < U.size() && U[j] == U[i+j]) ++j;
        A[i] = j;
        if(j == 0) {
            ++i;
            continue;
        }
        int k = 1;
        while(i + k < U.size() && k + A[k] < j) A[i+k] = A[k], k++;
        i += k;
        j -= k;
    }
    //int ret = 0;
    for(int i = S.size() + 1; i < U.size(); i++) {
        int val = U.size() - i;
        if(A[i] == val) return val;
    }
    return 0;
}

int f(string S) {
    for(int i = 1; i <= S.size(); i++) {
        bool ok = true;
        for(int j = 0; i + j < S.size(); j++) {
            if(S[j] != S[j+i]) ok = false;
        }
        if(ok) return i;
    }
}

int main() {
    cin >> N;
    S.resize(N + 1);
    for(int i = 1; i <= N; i++) {
        cin >> S[i];
    }
    for(int i = 1; i <= N; i++) {
        for(int j = 1; j <= N; j++) {
            if(i == j) continue;
            if(contain(S[i], S[j])) {
                S.erase(S.begin() + i);
                N--;
                i--;
                break;
            }
        }
    }
    int source = 0;
    int target = 2 * N + 1;
    PrimalDual<int> graph(N * 2 + 2);
    for(int i = 1; i <= N; i++) {
        graph.add_edge(source, i, 1, 0);
        graph.add_edge(i, i + N, 1, f(S[i]));
        graph.add_edge(i + N, target, 1, 0);
    }
    for(int i = 1; i <= N; i++) {
        for(int j = 1; j <= N; j++) {
            if(i == j) continue;
            int val = connect(S[i], S[j]);
            graph.add_edge(i, j + N, 1, S[j].size() - val);
            //cerr << i << " " << j << " " << S[j].size() - val << endl;
        }
    }
    cout << graph.min_cost_flow(source, target, N) << endl;
    //for(int i = 1; i <= N; i++) cerr << S[i] << endl;
}


Measured memory_bytes: 3572