#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
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;
}

#ifdef DEBUG
void debug() { cerr << "\n"; }
template <class T> void debug(const T &x) { cerr << x << "\n"; }
template <class T, class... Args> void debug(const T &x, const Args &... args) {
    cerr << x << " ";
    debug(args...);
}
template <class T> void debugVector(const vector<T> &v) {
    for(const T &x : v) {
        cerr << x << " ";
    }
    cerr << "\n";
}
#else
template <class T, class... Args>
void debug(const T &x, const Args &... args) {}
template <class T> void debugVector(const vector<T> &v) {}
#endif

using ll = long long;
#define ALL(v) (v).begin(), (v).end()
#define RALL(v) (v).rbegin(), (v).rend()
const double EPS = 1e-7;
const int INF = 1 << 30;
const ll LLINF = 1LL << 60;
constexpr int MOD = 1000000007;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

//-------------------------------------

// 最初にbaseをgenBase()でランダムに生成すること！！！！！！！！！
// RollingHash(s, base) := 文字列sのハッシュテーブルを計算する
// get(l, r) := [l, r)のハッシュ値を求める
// connect(h1, h2, h2len) := ハッシュ値h1と, 長さh2lenのハッシュ値h2を結合する。
// LCP(b, l1, r1, l2, r2) := 区間[l1, r1)と、ハッシュテーブルがbである区間[l1,
// r2)の文字列の 最長共通接頭辞の長さを求める。
struct RollingHash {
    using ull = unsigned long long;
    using ui128 = __uint128_t;
    static const ull mod = (1ULL << 61) - 1;
    const ull base;
    vector<ull> hashed, power;

    inline ull add(ull a, ull b) {
        if((a += b) >= mod) {
            a -= mod;
        }
        return a;
    }
    inline ull mul(ull a, ull b) {
        ui128 t = (ui128)a * b;
        ull na = t >> 61;
        ull nb = t & mod;
        if((na += nb) >= mod) {
            na -= mod;
        }
        return na;
    }
    static inline ull genBase() {
        random_device seed_gen;
        mt19937_64 engine(seed_gen());
        uniform_int_distribution<ull> rand(1, mod - 1);
        return rand(engine);
    }
    RollingHash() = default;
    RollingHash(const string &s, ull base) : base(base) {
        int n = (int)s.size();
        hashed.assign(n + 1, 0);
        power.assign(n + 1, 0);
        power[0] = 1;
        for(int i = 0; i < n; i++) {
            power[i + 1] = mul(power[i], base);
            hashed[i + 1] = add(mul(hashed[i], base), s[i]);
        }
    }
    ull get(int l, int r) {
        return add(hashed[r], mod - mul(hashed[l], power[r - l]));
    }
    ull connect(ull h1, ull h2, int h2len) {
        return add(mul(h1, power[h2len]), h2);
    }
    int LCP(RollingHash &b, int l1, int r1, int l2, int r2) {
        assert(mod == b.mod);
        int len = min(r1 - l1, r2 - l2);
        int low = -1, high = len + 1;
        while(high - low > 1) {
            int mid = (low + high) >> 1;
            if(get(l1, l1 + mid) == b.get(l2, l2 + mid)) {
                low = mid;
            } else {
                high = mid;
            }
        }
        return low;
    }
};

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    int N;
    cin >> N;
    vector<string> s(N);
    for(int i = 0; i < N; i++) {
        cin >> s[i];
    }
    sort(ALL(s), [](const string &a, const string &b) {
        return (a.size() < b.size());
    });
    gp_hash_table<RollingHash::ull, ll> cnt[26];
    auto base = RollingHash::genBase();
    ll ans = 0;
    for(int i = 0; i < N; i++) {
        int sz = (int)s[i].size();
        vector<int> exist;
        int num = 0;
        for(int j = 0; j < sz; j++) {
            num |= (1 << (s[i][j] - 'a'));
            exist.emplace_back(num);
        }
        reverse(ALL(exist));
        reverse(ALL(s[i]));
        RollingHash rh(s[i], base);
        if(sz <= 1) {
            cnt[s[i][0] - 'a'][0ULL]++;
            continue;
        }
        for(int j = 0; j < sz - 1; j++) {
            for(int k = 0; k < 26; k++) {
                if(exist[j] & (1 << k)) {
                    auto it = cnt[k].find(rh.get(0, j));
                    if(it != cnt[k].end()) {
                        ans += it->second;
                    }
                }
            }
        }
        cnt[s[i].back() - 'a'][rh.get(0, sz - 1)]++;
    }
    cout << ans << "\n";
}

Measured memory_bytes: 24852