// Author: Tyler Wang

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdlib>
#include <deque>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <numeric>
#include <optional>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>

using namespace std;

template <class C>
constexpr auto ssize(const C& c)
    -> std::common_type_t<std::ptrdiff_t,
                          std::make_signed_t<decltype(c.size())>> {
  using R = std::common_type_t<std::ptrdiff_t,
                               std::make_signed_t<decltype(c.size())>>;
  return (R)c.size();
}

template <class T, std::ptrdiff_t N>
constexpr std::ptrdiff_t ssize(const T (&)[N]) noexcept {
  return N;
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, bool> has_single_bit(
    T x) noexcept {
  return x != 0 && (x & (x - 1)) == 0;
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, int> countl_zero(
    T x) noexcept {
  if constexpr (sizeof(T) <= sizeof(unsigned)) {
    return __builtin_clz(x) - (std::numeric_limits<unsigned>::digits -
                               std::numeric_limits<T>::digits);
  } else if constexpr (sizeof(T) <= sizeof(unsigned long)) {
    return __builtin_clzl(x) - (std::numeric_limits<unsigned long>::digits -
                                std::numeric_limits<T>::digits);
  } else {
    static_assert(sizeof(T) <= sizeof(unsigned long long));
    return __builtin_clzll(x) -
           (std::numeric_limits<unsigned long long>::digits -
            std::numeric_limits<T>::digits);
  }
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, int> countr_zero(
    T x) noexcept {
  if constexpr (sizeof(T) <= sizeof(unsigned)) {
    return __builtin_ctz(x);
  } else if constexpr (sizeof(T) <= sizeof(unsigned long)) {
    return __builtin_ctzl(x);
  } else {
    static_assert(sizeof(T) <= sizeof(unsigned long long));
    return __builtin_ctzll(x);
  }
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, int> popcount(T x) noexcept {
  if constexpr (sizeof(T) <= sizeof(unsigned)) {
    return __builtin_popcount(x);
  } else if constexpr (sizeof(T) <= sizeof(unsigned long long)) {
    return __builtin_popcountl(x);
  } else {
    static_assert(sizeof(T) <= sizeof(unsigned long long));
    return __builtin_popcountll(x);
  }
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, T> bit_width(T x) noexcept {
  return (T)(std::numeric_limits<T>::digits - countl_zero(x));
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, T> bit_ceil(T x) noexcept {
  return (T)(x <= 1 ? 1 : (T)1 << bit_width((T)(x - 1)));
}

template <typename T>
constexpr std::enable_if_t<std::is_unsigned_v<T>, T> bit_floor(T x) noexcept {
  return (T)(x == 0 ? 0 : (T)1 << (bit_width(x) - 1));
}

#if defined(__GNUC__) && !defined(__clang__)

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

template <typename Key, typename Compare = std::less<Key>,
          typename Allocator = std::allocator<Key>>
using ordered_set =
    __gnu_pbds::tree<Key, __gnu_pbds::null_type, Compare,
                     __gnu_pbds::rb_tree_tag,
                     __gnu_pbds::tree_order_statistics_node_update, Allocator>;

template <typename Key, typename T, typename Compare = std::less<Key>,
          typename Allocator = std::allocator<std::pair<const Key, T>>>
using ordered_map =
    __gnu_pbds::tree<Key, T, Compare, __gnu_pbds::rb_tree_tag,
                     __gnu_pbds::tree_order_statistics_node_update, Allocator>;

#endif

template <typename Fun>
class y_combinator_result {
 public:
  template <typename T>
  explicit y_combinator_result(T&& fun) : fun_(std::forward<T>(fun)) {}

  template <typename... Args>
  decltype(auto) operator()(Args&&... args) {
    return fun_(std::ref(*this), std::forward<Args>(args)...);
  }

 private:
  Fun fun_;
};

template <typename Fun>
decltype(auto) y_combinator(Fun&& fun) {
  return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun));
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::optional<T>& opt);

template <typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p);

template <typename... Ts>
std::ostream& operator<<(std::ostream& os, const std::tuple<Ts...>& t);

template <typename Container,
          std::enable_if_t<!std::is_convertible_v<Container, std::string_view>,
                           typename Container::const_iterator>* = nullptr>
std::ostream& operator<<(std::ostream& os, const Container& c);

template <typename ContainerAdaptor,
          typename ContainerAdaptor::container_type* = nullptr>
std::ostream& operator<<(std::ostream& os, const ContainerAdaptor& a);

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::optional<T>& opt) {
  return opt ? os << *opt : os << "nullopt";
}

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

template <typename... Ts>
std::ostream& operator<<(std::ostream& os, const std::tuple<Ts...>& t) {
  return std::apply(
      [&os](const Ts&... args) -> std::ostream& {
        os << '{';
        int i = 0;
        ((os << (i++ == 0 ? "" : ", ") << args), ...);
        return os << '}';
      },
      t);
}

template <typename Container,
          std::enable_if_t<!std::is_convertible_v<Container, std::string_view>,
                           typename Container::const_iterator>*>
std::ostream& operator<<(std::ostream& os, const Container& c) {
  os << '{';
  for (auto it = c.begin(); it != c.end(); ++it) {
    os << (it == c.begin() ? "" : ", ") << *it;
  }
  return os << '}';
}

template <typename ContainerAdaptor, typename ContainerAdaptor::container_type*>
std::ostream& operator<<(std::ostream& os, const ContainerAdaptor& a) {
  class subadaptor : public ContainerAdaptor {
   public:
    const auto& c() const { return ContainerAdaptor::c; }
  };
  return os << static_cast<const subadaptor&>(a).c();
}

namespace detail {

template <typename... Ts>
void print(std::ostream& os, int line, std::string_view keys,
           const Ts&... vals) {
  if constexpr (sizeof...(Ts) == 0) {
    os << "  " << line << " |" << std::endl;
  } else {
    std::vector<std::string_view> key_list;
    key_list.reserve(sizeof...(Ts));
    int start = 0, paren = 0;
    for (int i = 0; i < (int)keys.size(); ++i) {
      switch (keys[i]) {
        case '(':
        case '[':
        case '{':
          ++paren;
          break;
        case ')':
        case ']':
        case '}':
          --paren;
          break;
        case ',':
          if (paren == 0) {
            key_list.push_back(keys.substr(start, i - start));
            start = i;
          }
          break;
      }
    }
    key_list.push_back(keys.substr(start));
    assert(key_list.size() == sizeof...(Ts));
    os << "  " << line << " | ";
    int i = 0;
    ((os << key_list[i++] << " = " << vals), ...);
    os << std::endl;
  }
}

}  // namespace detail

#ifdef TYLER
#define debug(...) \
  detail::print(std::cerr, __LINE__, #__VA_ARGS__ __VA_OPT__(, ) __VA_ARGS__)
#else
#define debug(...) ((void)0)
#endif

template <typename Container>
class roll_hash {
 public:
  roll_hash(const Container& cont = Container()) : muls_(rand2()) {
    init(cont);
  }

  roll_hash(const roll_hash& other, const Container& cont)
      : muls_(other.muls_) {
    init(cont);
  }

  int size() const { return (int)pows_[0].size() - 1; }

  void push_back(typename Container::value_type val) {
    for (int k = 0; k < 2; ++k) {
      pows_[k].push_back(
          (int)((long long)pows_[k].back() * muls_[k] % MODS[k]));
      prefs_[k].push_back(
          (int)(((long long)prefs_[k].back() * muls_[k] + val) % MODS[k]));
    }
  }

  void pop_back() {
    for (int k = 0; k < 2; ++k) {
      pows_[k].pop_back();
      prefs_[k].pop_back();
    }
  }

  // Hashes the closed range [first, last].
  long long operator()(int first, int last) const {
    assert(first <= last);
    ++last;
    std::array<long long, 2> vals;
    for (int k = 0; k < 2; ++k) {
      vals[k] = prefs_[k][last] -
                (long long)prefs_[k][first] * pows_[k][last - first] % MODS[k];
      if (vals[k] < 0) {
        vals[k] += MODS[k];
      }
    }
    return (vals[0] << 32) + vals[1];
  }

  long long operator()(const Container& other) const {
    std::array<long long, 2> vals = {0, 0};
    for (int k = 0; k < 2; ++k) {
      for (int i = 0; i < (int)other.size(); ++i) {
        vals[k] = (vals[k] * muls_[k] + other[i]) % MODS[k];
      }
    }
    return (vals[0] << 32) + vals[1];
  }

 private:
  static constexpr std::array<int, 2> MODS = {2'147'483'629, 2'147'483'647};
  std::array<int, 2> muls_;
  std::array<std::vector<int>, 2> pows_, prefs_;

  static std::array<int, 2> rand2() {
    std::mt19937 thanos(
        (std::uint_fast32_t)std::chrono::high_resolution_clock::now()
            .time_since_epoch()
            .count());
    std::uniform_int_distribution<int> snap(1'000'000, 1'000'000'000);
    return std::array{snap(thanos), snap(thanos)};
  }

  void init(const Container& cont) {
    int n = (int)cont.size();
    for (int k = 0; k < 2; ++k) {
      pows_[k].reserve(n + 1);
      pows_[k].push_back(1);
      for (int i = 0; i < n; ++i) {
        pows_[k].push_back((int)((long long)pows_[k][i] * muls_[k] % MODS[k]));
      }
      prefs_[k].reserve(n + 1);
      prefs_[k].push_back(0);
      for (int i = 0; i < n; ++i) {
        prefs_[k].push_back(
            (int)(((long long)prefs_[k][i] * muls_[k] + cont[i]) % MODS[k]));
      }
    }
  }
};

int main() {
  auto start_time = std::chrono::steady_clock::now();
  std::mt19937 thanos(
      (std::uint_fast32_t)start_time.time_since_epoch().count());
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  std::cout.precision(24);
  int n;
  cin >> n;
  vector<string> ss(n);
  for (string& s : ss) {
    cin >> s;
    reverse(s.begin(), s.end());
  }
  roll_hash<string> base;
  vector<long long> poss, vals;
  for (const string& s : ss) {
    vector<int> cnt(26);
    for (char c : s) {
      ++cnt[c - 'a'];
    }
    roll_hash hasher(base);
    for (int i = 0; i < ssize(s); ++i) {
      for (int j = 0; j < 26; ++j) {
        if (cnt[j] > 0) {
          hasher.push_back((char)('a' + j));
          poss.push_back(hasher(0, i));
          hasher.pop_back();
        }
      }
      hasher.push_back(s[i]);
      --cnt[s[i] - 'a'];
    }
    assert(hasher.size() == ssize(s));
    vals.push_back(hasher(0, hasher.size() - 1));
  }
  sort(poss.begin(), poss.end());
  long long ans = -n;
  for (long long x : vals) {
    auto [lower, upper] = equal_range(poss.begin(), poss.end(), x);
    ans += upper - lower;
  }
  cout << ans << '\n';
  return 0;
}

Measured memory_bytes: 287464