#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
#include <numeric>
#include <algorithm>
#include <functional>
#include <fstream>
#include <array>
#include <map>
#include <queue>
#include <time.h>
#include <limits.h>
#include <set>
#include <stack>
#include <random>
#include <complex>
#include <unordered_map>
#include <assert.h>
#include <unordered_set>
#define rep(i,s,n) for(int i = (s); (n) > i; i++)
#define REP(i,n) rep(i,0,n)
#define RANGE(x,a,b) (min(a,b) <= (x) && (x) <= max(a,b)) //hei
#define DUPLE(a,b,c,d) (RANGE(a,c,d) || RANGE(b,c,d) || RANGE(c,a,b) || RANGE(d,a,b))
#define INCLU(a,b,c,d) (RANGE(a,c,d) && (b,c,d))
#define PW(x) ((x)*(x))
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define MODU 998244353LL 
#define bitcheck(a,b)   ((a >> b) & 1)
#define bitset(a,b)      ( a |= (1 << b))
#define bitunset(a,b)    (a &= ~(1 << b))
#define MP(a,b) make_pair((a),(b))
#define Manh(a,b) (abs((a).first-(b).first) + abs((a).second - ((b).second))
#define pritnf printf
#define scnaf scanf
#define itn int
#define PI 3.141592653589
 
 
#define izryt bool
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
template<typename A, size_t N, typename T>
void Fill(A(&array)[N], const T & val) {
	std::fill((T*)array, (T*)(array + N), val);
}
 
//[a, b)
#define Getsum(ar, a,b) (ar[b] - ar[a])
#define INF 10000000000000000LL
#define chmax(a,b) a = max(a,b)
#define chmin(a,b) a = min(a,b)
 
struct Edge {
	int from, to;
	ll w;
	bool operator<(const Edge& rhs) const {
		return MP(w, MP(from, to)) < MP(rhs.w, MP(rhs.from, rhs.to));
	}
 
};
typedef vector<vector<Edge>> Graph;
typedef unsigned long long ull;
 
 
inline ll ksum(ll n, ll k){
  return k * (2*n - k - 1);
}

pii updtp2(pii p, int nw){
  if(p.first == -1) p.first = nw;
  else if(p.second == -1) p.second = nw;
  else if(p.first >= nw) {
    p.second = p.first;
    p.first = nw;
  }
  else if(p.second >= nw) p.second = nw;
  return p;
}
 
typedef pair<ll,ll> Hash;

#define isValid(y,x) (y >=0 && y < n && x >= 0 && x < m)
class RollingHash {
    static const ll base1 = 1009;
    static const ll base2 = 2009;
    static const ll mod1 = 1000000007;
    static const ll mod2 = 1000000009;
    vector<ll> hash1, hash2, pow1, pow2;

public:
    RollingHash(const string &S) {
        int n = (int) S.size();
        hash1.assign(n + 1, 0);
        hash2.assign(n + 1, 0);
        pow1.assign(n + 1, 1);
        pow2.assign(n + 1, 1);
        for (int i = 0; i < n; ++i) {
            hash1[i + 1] = (hash1[i] * base1 + S[i]) % mod1;
            hash2[i + 1] = (hash2[i] * base2 + S[i]) % mod2;
            pow1[i + 1] = (pow1[i] * base1) % mod1;
            pow2[i + 1] = (pow2[i] * base2) % mod2;
        }
    }

    /**
     * S の [l, r) のハッシュ値を返す
     * O(1)
     */
    inline pair<ll, ll> get(int l, int r) const {
        ll res1 = hash1[r] - hash1[l] * pow1[r - l] % mod1;
        if (res1 < 0) res1 += mod1;
        ll res2 = hash2[r] - hash2[l] * pow2[r - l] % mod2;
        if (res2 < 0) res2 += mod2;
        return make_pair(res1, res2);
    }

    /**
     * S のハッシュ値を返す
     * O(1)
     */
    inline pair<ll, ll> hash() const {
        return get(0, (int) hash1.size() - 1);
    }

    /**
     * LCP (Longest Common Prefix)
     * O( log N )
     */
    inline int getLCP(int a, int b) const {
        int len = min((int) hash1.size() - a, (int) hash1.size() - b);
        int low = 0, high = len;
        while (high - low > 1) {
            int mid = (low + high) >> 1;
            if (get(a, a + mid) != get(b, b + mid)) high = mid;
            else low = mid;
        }
        return low;
    }

    /**
     * hash h1 と 長さ h2_len の文字列の hash h2 を結合
     */
    pair<ll, ll> concat(pair<ll, ll> h1, pair<ll, ll> h2, int h2_len) {
        return make_pair((h1.first * pow1[h2_len] + h2.first) % mod1, (h1.second * pow2[h2_len] + h2.second) % mod2);
    }
};

const pii Dir[4] = {{-1,0}, {0,1}, {1,0}, {0,-1}};

int main(){
	int n;
  cin >> n;
  vector<string> s(n), tl(n);
  vector<RollingHash> ls;
  ls.reserve(n);
  REP(i,n) {
    cin >> s[i];
  }
  sort(s.begin(),s.end(),
    [](const string& a, const string& b){
      return a.size() < b.size();
    }
  );

  REP(i,n){
    tl[i] = s[i].substr(1, s[i].size() - 1);
    ls.push_back(RollingHash(tl[i]));
  }

  ll ans = 0;
  map<Hash, int> cnt[26];

  REP(i, n)
  {

    bool isok[26] = {};
    REP(j, s[i].size())
    {
      isok[s[i][j] - 'a'] = true;

      REP(k,26){
        if(isok[k]){
          Hash hash = ls[i].get(j, tl[i].size());
          if(cnt[k].count(hash) > 0)
            ans += cnt[k][hash];
        }
      }
    }

    cnt[s[i][0] - 'a'][ls[i].hash()]++;
  }

  cout << ans << endl;
	return 0;
} 

Measured memory_bytes: 87392