#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

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

const long long INF = 1e18;
//const ll mod = 1000000007;
ll num[1050000][26];
template< int char_size >
struct TrieNode {
  int nxt[char_size];

  int exist;
  vector< int > accept;

  TrieNode() : exist(0) {
    memset(nxt, -1, sizeof(nxt));
  }
};

template< int char_size, int margin >
struct Trie {
  using Node = TrieNode< char_size >;

  vector< Node > nodes;
  int root;

  Trie() : root(0) {
    nodes.push_back(Node());
  }

  void update_direct(int node, int id) {
    nodes[node].accept.push_back(id);
  }

  void update_child(int node, int child, int id) {
    ++nodes[node].exist;
  }

  void add(const string &str, int str_index, int node_index, int id) {
    if(str_index + 1 == str.size()) {
        ll c = str[str_index] - margin;
        num[node_index][c]++;
    }
    if(str_index == str.size()) {
      update_direct(node_index, id);
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) {
        nodes[node_index].nxt[c] = (int) nodes.size();
        nodes.push_back(Node());
      }
      add(str, str_index + 1, nodes[node_index].nxt[c], id);
      update_child(node_index, nodes[node_index].nxt[c], id);
    }
  }

  void add(const string &str, int id) {
    add(str, 0, 0, id);
  }

  void add(const string &str) {
    add(str, nodes[0].exist);
  }

  void query(const string &str, const function< void(int) > &f, int str_index, int node_index) {
    for(auto &idx : nodes[node_index].accept) f(idx);
    if(str_index == str.size()) {
      return;
    } else {
      const int c = str[str_index] - margin;
      if(nodes[node_index].nxt[c] == -1) return;
      query(str, f, str_index + 1, nodes[node_index].nxt[c]);
    }
  }

  void query(const string &str, const function< void(int) > &f) {
    query(str, f, 0, 0);
  }

  int count() const {
    return (nodes[0].exist);
  }

  int size() const {
    return ((int) nodes.size());
  }
};
ll ans;
ll N;
vector<string> S;
ll tmpnum[26];
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    Trie<26, 'a'> trie;
    cin >> N;
    S.resize(N);
    for(int i = 0; i < N; i++) {
        cin >> S[i];
        reverse(S[i].begin(), S[i].end());
        trie.add(S[i]);
    }
    /*
    for(int i = 0; i < trie.size(); i++) {
        for(int j = 0; j < 26; j++) {
            if(num[i][j]) cerr << i << " " << j << " " << num[i][j] << endl;
        }
    }
    */
    for(int i = 0; i < N; i++) {
        ll node = 0;
        for(ll j = 0; j < S[i].size(); j++) {
            tmpnum[(int)(S[i][j] - 'a')]++;
        }
        for(int j = 0; j < S[i].size(); j++) {
            for(int k = 0; k < 26; k++) {
                if(tmpnum[k]) {
                    //cerr << i << " " << j << " " << k << " " << tmpnum[k] << endl;
                    ans += num[node][k];
                }
            }
            node = trie.nodes[node].nxt[(int)(S[i][j] - 'a')];
            tmpnum[(int)(S[i][j] - 'a')]--;
        }
    }
    cout << ans - N << endl;
    return 0;
}


Measured memory_bytes: 352072