// clang-format off
	#include <bits/stdc++.h>
	using namespace std; using ll = long long; using uint = unsigned int; using ull = unsigned long long;
	#define SFINAE(x, ...)	template <class, class = void> struct x : false_type {}; template <class T> struct x<T, void_t<__VA_ARGS__>> : true_type {};
	SFINAE(DefaultIO, decltype(cout << declval<T &>()))
	SFINAE(IsTuple, typename tuple_size<T>::type)
	SFINAE(Iterable, decltype(begin(declval<T>())))
	template <class T> constexpr char Space(const T &) { return (Iterable<T>::value or IsTuple<T>::value) ? '\n' : ' '; }
	template <auto &os> struct Writer {
		template <class T> void Impl(T const &t) const {
			if constexpr (DefaultIO<T>::value) os << t;
			else if constexpr (Iterable<T>::value) { int i = 0; for (auto &&x : t) ((i++) ? (os << Space(x), Impl(x)) : Impl(x)); }
			else if constexpr (IsTuple<T>::value) apply([this](auto const &... args) { int i = 0; (((i++) ? (os << ' ', Impl(args)) : Impl(args)), ...);}, t);
			else static_assert(IsTuple<T>::value, "No matching type for print");
		}
		template <class F, class... Ts> auto &operator()(F const &f, Ts const &... ts) const { return Impl(f), ((os << ' ', Impl(ts)), ...), os << '\n', *this; }
	};
	template <auto &is> struct Reader {
		template <class T> auto& Rd(T &t) const {
			if constexpr (DefaultIO<T>::value) is >> t;
			else if constexpr (Iterable<T>::value) for (auto &x : t) Rd(x);
			else if constexpr (IsTuple<T>::value) apply([this](auto &... args) { (Rd(args), ...); }, t);
			else static_assert(IsTuple<T>::value, "No matching type for read");
			return *this;
		}
		template <class T> auto operator[](T t) const { Rd(t); return t; }
		template <class... Ts> auto operator()(Ts... ts) const { (Rd(ts), ...); return tuple{move(ts)...}; }
	};
	#ifdef NARUT_LOCAL
	#define Debug(...) cerr << "\033[0;31m", Writer<cerr>{}(__VA_ARGS__), cerr << "\033[0m\n"
	#else
	#define Debug(...) 0
	#endif
	[[maybe_unused]] constexpr Reader<cin> Cin; [[maybe_unused]] constexpr Writer<cout> Cout;
	#define FOR(i, j, n) for (int i = int(j); i < int(n); ++i)
	#define ROF(i, j, n) for (int i = int(n) - 1; i >= int(j); --i)
	#define let auto const
// clang-format on

struct CharIndex {
	auto operator()(char c) const { return c - 'a'; }
};

template <size_t ASize = 26, class CountT = int, class IndexFunc = CharIndex> struct Trie : private IndexFunc {
	struct Node {
		array<Node *, ASize> ch{};
		mutable CountT count{};
	};

	deque<Node> D{{}};
	Trie(IndexFunc func = {}) : IndexFunc(func) {}

	Node *Root() { return &D.front(); }
	Node const *Root() const { return &D.front(); }

	template <class It> Node const *Get(Node const *root, It first, It last) const {
		auto cur = root;
		for (; first != last and cur; ++first) cur = cur->ch[(*this)(*first)];
		return cur;
	}
	template <class It> Node const *Get(It first, It last) const { return Get(Root(), first, last); }

	template <class It> Node *GetCreate(Node *root, It first, It last) {
		auto cur = root;
		for (; first != last; ++first) {
			auto &nxt = cur->ch[(*this)(*first)];
			cur = nxt ? nxt : nxt = &D.emplace_back();
		}
		return cur;
	}
	template <class It> Node *GetCreate(It first, It last) { GetCreate(Root(), first, last); }

	template <class It> void Add(Node *root, It first, It last) { GetCreate(root, first, last)->count++; }
	template <class It> void Add(It first, It last) { Add(Root(), first, last); }

	template <class It> void Remove(Node *root, It first, It last) {
		if (auto node = Get(first, last)) node->count--;
	}
	template <class It> void Remove(It first, It last) { Remove(Root(), first, last); }

	template <class It> auto Count(Node *root, It first, It last) const {
		auto it = Get(first, last);
		return it ? it->count : CountT{};
	}
	template <class It> auto Count(It first, It last) { return Count(Root(), first, last); }

	template <class F> void TraverseAll(Node const *root, F &&func) const {
		if (!root) return;
		func(root);
		for (auto ch : root->ch) TraverseAll(ch, func);
	}
	template <class F> void TraverseAll(F &&func) const { return TraverseAll(Root(), func); }

	template <class It, class Func> void Traverse(Node *root, It first, It last, Func &&f) const {
		auto cur = root;
		for (f(cur); first != last; f(cur), ++first) {
			cur = cur->ch[(*this)(*first)];
			if (!cur) return;
		}
	}
	template <class It, class F> void Traverse(It first, It last, F &&func) const {
		Traverse(Root(), first, last, func);
	}

	template <class It, class F> void TraverseCreate(Node *root, It first, It last, F &&func) {
		auto cur = root;
		for (func(cur); first != last; func(cur), ++first) {
			auto &nxt = cur->ch[(*this)(*first)];
			cur = nxt ? nxt : nxt = &D.emplace_back();
		}
	}
	template <class It, class F> void TraverseCreate(It first, It last, F &&func) {
		TraverseCreate(Root(), first, last, func);
	}
};

auto Main() {
	let n = Cin[0];
	let S = Cin[vector<string>(n)];
	Trie trie;
	for (let &s : S) {
		trie.Add(s.rbegin(), s.rend());
	}
	ll ans = 0;
	for (let &s : S) {
		array<int, 26> cnt{};
		for (char c : s) cnt[c - 'a']++;
		auto cur = as_const(trie).Root();
		for (auto it = rbegin(s); cur and it != rend(s); ++it) {
			FOR(i, 0, 26) {
				if (cnt[i]) {
					array C = {'a' + i};
					auto tmp = trie.Get(cur, C.begin(), C.end());
					if (tmp) ans += tmp->count;
				}
			}
			cnt[*it - 'a']--;
			cur = trie.Get(cur, it, it + 1);
		}
	}
	trie.TraverseAll([&ans](auto node) {
		if (auto c = node->count) {
			ans -= c * c;
			ans += c * (c - 1) / 2;
		}
	});
	cout << ans;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
	cout << fixed << setprecision(10);
#ifdef NARUT_LOCAL
	assert(freopen("io/test.in", "r", stdin));
	cin.exceptions(cin.badbit | cin.failbit);
	cerr << fixed << setprecision(10);
#endif

	Main();
}


Measured memory_bytes: 269764