#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

#include <iostream>
#include <complex>
#include <string>
#include <algorithm>
#include <numeric>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

#include <functional>
#include <cassert>

typedef long long ll;
using namespace std;

#ifndef LOCAL
#define debug(x) ;
#else
#define debug(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;

template <typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  out << "{" << p.first << ", " << p.second << "}";
  return out;
}

template <typename T>
ostream &operator<<(ostream &out, const vector<T> &v) {
  out << '{';
  for (const T &item : v) out << item << ", ";
  out << "\b\b}";
  return out;
}
#endif

#define mod 1000000007 //1e9+7(prime number)
#define INF 1000000000 //1e9
#define LLINF 2000000000000000000LL //2e18
#define SIZE 200010

/* KMP */

// A[i] := 文字列S[0,i-1]の接頭辞と接尾辞が最大何文字一致しているか (i-1未満)
// len(A) == S.size() + 1

void KMP(const char *S, int *A){
  A[0] = -1;
  int j = -1, n = strlen(S);
  for (int i = 0; i < n; i++) {
    while (j >= 0 && S[i] != S[j]) j = A[j];
    j++;

    //KMP
    //if (S[i+1] == S[j]) A[i+1] = A[j];
    //else A[i+1] = j;

    //MP
    A[i+1] = j;
  }
}

/* Rolling Hash */
// n = 9973, 10007

struct RollingHash{
  int N, base;
  vector<ll> hash, pow;

  template <typename Type>
  void init(int _base, int n, Type *arr)
  {
    N = n;
    base = _base;
    hash.assign(n+1, 0);
    pow.assign(n+1, 0);

    hash[0] = 0;
    pow[0] = 1;
    for(int i=0; i<N; i++){
      hash[i+1] = (hash[i] + arr[i]) * base % mod;
      pow[i+1] = pow[i] * base % mod;
    }
  }

  // get [l,r)
  ll getHash(int l, int r) {
    return (mod + hash[r] - hash[l] * pow[r-l] % mod) % mod;
  }
};

/* Minimum Cost Flow */

struct MinimumCostFlow{

  typedef pair<int,int> P;

  struct edge {
    int to, cap, cost, rev;
    edge(int a, int b, int c, int d):to(a), cap(b), cost(c), rev(d) {}
  };

  vector<vector<edge>> G;
  vector<int> h, dist, prevv, preve;
  int V;

  MinimumCostFlow(int v):
    G(v, vector<edge>()), prevv(v, 0), preve(v, 0), V(v) {}

  int add_edge(int from, int to, int cap, int cost){
    int id = G[from].size();

    G[from].push_back(edge(to, cap, cost, G[to].size()));
    G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));

    return id;
  }

  int solve(int s, int t, int f){
    int res = 0;
    h.assign(V,0);
    while(f > 0){
      priority_queue<P, vector<P>, greater<P>> pq;
      dist.assign(V, INF);
      dist[s] = 0;
      pq.push(P(0, s));
      while(pq.size()){
        P p = pq.top(); pq.pop();
        int v = p.second;
        if(dist[v] < p.first) continue;

        for(int i = 0; i < (int)G[v].size(); i++){
          edge &e = G[v][i];
          int d = dist[v] + e.cost + h[v] - h[e.to];
          if(e.cap > 0 && dist[e.to] > d){
            dist[e.to] = d;
            prevv[e.to] = v;
            preve[e.to] = i;
            pq.push(P(dist[e.to], e.to));
          }
        }
      }
      if(dist[t] == INF) return -1;

      for(int v = 0; v < V; v++) h[v] += dist[v];

      int d = f;
      for(int v = t; v != s; v = prevv[v])
        d = min(d, G[prevv[v]][preve[v]].cap);

      f -= d;
      res += d * h[t];

      for(int v = t; v != s; v = prevv[v]){
        edge &e = G[prevv[v]][preve[v]];
        e.cap -= d;
        G[v][e.rev].cap += d;
      }
    }

    return res;
  }
};

char s[100][1001];
int slen[100];
int cost[100][100];

int main(){
  int N;

  scanf("%d", &N);

  for (int i=0; i<N; i++) {
    scanf("%s", s[i]);
    slen[i] = strlen(s[i]);
  }


  for(int i=0; i<N; i++) {
    int a[1001] = {};
    KMP(s[i], a);

    cost[i][i] = slen[i] - a[slen[i]];
  }

  RollingHash hash[100];

  for(int i=0; i<N; i++) {
    hash[i].init(9973, slen[i], s[i]);
  }

  for(int i=0; i<N; i++) {
    for(int j=0; j<N; j++) {
      if (i == j) continue;
      cost[i][j] = slen[i];

      for(int x=1; x<=min(slen[i], slen[j]); x++) {
        if (hash[i].getHash(slen[i]-x, slen[i]) ==
            hash[j].getHash(0, x))
        cost[i][j] = slen[i] - x;
      }
    }
  }

  MinimumCostFlow flow(N * 2 + 2);

  for(int i=0; i<N; i++) {
    for(int j=0; j<N; j++) {
      //cerr << cost[i][j] << " ";
      flow.add_edge(i, N+j, 1, cost[i][j]);
    }
    //cerr << endl;
  }

  for(int i=0; i<N; i++) {
    flow.add_edge(N*2, i, 1, 0);
    flow.add_edge(N+i, N*2+1, 1, 0);
  }

  int ans = flow.solve(N*2, N*2+1, N);

  cout << ans << endl;

  return 0;
}



Measured memory_bytes: 4912