#include<bits/stdc++.h>
#define TIME (1.0* clock()/CLOCKS_PER_SEC)
#define pb push_back
#define eb emplace_back
#define id1 (id<<1)
#define id2 (id<<1)|1
#define ll long long
#define ii pair<int,int>
#define vi vector<int>
#define vii vector<pair<int,int>>
#define vl vector<long long>
#define vll vector <pair<ll,ll>>
#define li pair<long long,int>
#define vil vector <pair<int,ll>>
#define db double
#define ff first
#define ss second
#define lb lower_bound
#define ub upper_bound
#define FOR(i, a, b) for (int i = (a); i <=(b); i++)
#define F0R(i, a) FOR(i, 0, a-1)
#define ROF(i, a, b) for (int i = (b); i >= (a); i--)
#define R0F(i, a) ROF(i, 0, a-1)
#define rep(a) F0R(_, a)
#define each(a, x) for (auto &a : x)
#define ALL(x) (x).begin(),(x).end()
#define pq priority_queue <li, vector <li>, greater <li>>
using namespace std;
const int maxn=1e5+5;
//const int MOD=1e9+7;
//const int MOD=998244353;
//const int dx[4]{1, 0, -1, 0}, dy[4]{0, 1, 0, -1};
int m;
vector<array<int,26>> T1;
vector<array<int,26>> T2;
const int BASE = 29;
const int MOD = 1e9 + 7;
int isEnd1[maxn];
int isEnd2[maxn];
string S[maxn];
string R[maxn];
int cnt[maxn];
vector<ll> powB;
void precompute_pow(int max_len){
powB.resize(max_len + 1);
powB[0] = 1;
for (int i = 1; i <= max_len; i++) {
powB[i] = (powB[i-1] * BASE) % MOD;
}
}
void addT1(string s){
int root = 0;
for (char x : s) {
int k = x - 'a';
if (T1[root][k] == 0) {
T1.emplace_back();
T1[root][k] = T1.size()-1;
}
root = T1[root][k];
}
isEnd1[root]++;
}
void addT2(string s){
int root = 0;
for (char x : s) {
int k = x - 'a';
if (T2[root][k] == 0) {
T2.emplace_back();
T2[root][k] = T2.size()-1;
}
root = T2[root][k];
}
isEnd2[root]++;
}
void build(const string &s) {
int n = s.length();
if (powB.empty()) precompute_pow(n);
vector<ll> hashF(n + 1), hashR(n + 1);
hashF[0] = 0;
for (int i=1;i<=n;i++){
hashF[i]=(hashF[i-1]*BASE+s[i-1])%MOD;
}
hashR[n] = 0;
for (int i=n-1;i>=0;i--){
hashR[i] = (hashR[i+1] * BASE + s[i]) % MOD;
}
auto checkpalindrome = [&](int l, int r) {
ll forward = (hashF[r+1] - hashF[l] * powB[r-l+1] % MOD + MOD) % MOD;
ll reverse = (hashR[l] - hashR[r+1] * powB[r-l+1] % MOD + MOD) % MOD;
return forward == reverse;
};
int root = 0;
for (int i=0;i<n;i++){
int k = s[i] - 'a';
if (T1[root][k] == 0) break;
root = T1[root][k];
if (checkpalindrome(i+1, n-1)) {
cnt[root]++;
}
}
}
int countPalindrome(string s){
int n = s.length();
int res=0;
if (powB.empty()) precompute_pow(n);
vector<ll> hashF(n + 1), hashR(n + 1);
hashF[0] = 0;
for (int i=1;i<=n;i++){
hashF[i]=(hashF[i-1]*BASE+s[i-1])%MOD;
}
hashR[n] = 0;
for (int i=n-1;i>=0;i--){
hashR[i] = (hashR[i+1] * BASE + s[i]) % MOD;
}
auto checkpalindrome = [&](int l, int r) {
ll forward = (hashF[r+1] - hashF[l] * powB[r-l+1] % MOD + MOD) % MOD;
ll reverse = (hashR[l] - hashR[r+1] * powB[r-l+1] % MOD + MOD) % MOD;
return forward == reverse;
};
int root1=0;
int root2=0;
for(int i=0;i<n;i++){
int k = s[i] - 'a';
if(T2[root2][k]==0) break;
root1=T1[root1][k];
root2=T2[root2][k];
if(isEnd1[root2] and checkpalindrome(i+1, n-1)) res+=isEnd2[root2]; // Si>Sj;
}
res+=isEnd2[root2]; //Si==Sj;
res+=cnt[root2];//Si<Sj;
return res;
}
void solve(){
T1.emplace_back();
T2.emplace_back();
cin >> m;
for(int i = 1; i <= m; i++){
cin >> S[i];
addT1(S[i]);
R[i]= S[i];
reverse(R[i].begin(), R[i].end());
addT2(R[i]);
}
for(int i=1;i<=m;i++) build(R[i]);
int val=0;
for(int i=1;val<=m;val++) val+=countPalindrome(S[i]);
cout<<val;
return;
}
signed main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
if (fopen("TASK.INP", "r")){
freopen("TASK.INP", "r", stdin);
freopen("TASK.OUT", "w", stdout);
}
int ntest = 1;
//cin >> ntest;
for(int i = 1; i <= ntest; i++) solve();
cerr << "\n" << "Time elapsed " << TIME << "s.\n";
return 0;
}