#include <bits/stdc++.h>
using namespace std;

using ll=long long;
typedef pair<int,int> P;
typedef pair<P,P> PP;
const ll MODA=1e9+7,MODB=17,MODC=998244353,MODD=123456789;
vector<PP> hsh[223456];
vector<int> v[26];

typedef int U;
struct SegmentTree{
  typedef vector<U> T;
  int n;
  U MIN=-1000000000,MAX=1000000000,eps=1;
  using F = function<T(T,T)>;;

  F f=[](T a,T b){
    T res;
    int nowa=0,nowb=0;
    while(nowa<a.size()||nowb<b.size()){
      if(nowa==a.size())res.push_back(b[nowb++]);
      else if(nowb==b.size())res.push_back(a[nowa++]);
      else{
        if(a[nowa]<b[nowb])res.push_back(a[nowa++]);
        else res.push_back(b[nowb++]);
      }
    }
    return res;
  };

  T ti=vector<U>();
  vector<T> dat;
  SegmentTree(){};
  SegmentTree(int n_){
    n=1;
    while(n<n_) n<<=1;
    dat.assign(n<<1,ti);
  }
  SegmentTree(const vector<U> &v){
    int n_=v.size();
    n=1;
    while(n<n_) n<<=1;
    dat.assign(n<<1,ti);
    for(int i=0;i<n_;i++)dat[n+i]=T(1,v[i]);
    for(int i=n-1;i;i--)
      dat[i]=f(dat[(i<<1)|0],dat[(i<<1),1]);
  }

  void build(vector<int> &v){
    int n_=v.size();
    n=1;
    while(n<n_) n<<=1;
    dat.assign(n<<1,ti);
    for(int i=0;i<n_;i++)dat[n+i]=T(1,v[i]);
    for(int i=n-1;i;i--)
      dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);
  }

  void init(int n_){
    n=1;
    while(n<n_) n<<=1;
    dat.assign(n<<1,ti);
  }

  int get(int x){
    return dat[x+n][0];
  }

  void set_val(int k,U x){
    dat[k+=n]=T(1,x);
    while(k>>=1)
      dat[k]=f(dat[(k<<1)|0],dat[(k<<1)|1]);
  }

  T query(int a,int b){  //[a,b)の範囲でのソート結果を返す
    T vl=ti,vr=ti;
    for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) vl=f(vl,dat[l++]);  //左端を使いたくなるのはブロックが奇数の時
      if(r&1) vr=f(dat[--r],vr);  //右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return f(vl,vr);
  }

  inline void CHMIN(U &a,T v){
    if(v.size()&&a>v[0])a=v[0];
  }
  inline void CHMAX(U &a,T v){
    if(v.size()&&a<v[0])a=v[0];
  }

  U mx(int a,int b){//[a,b)のmaxを返す
    U vl=MIN,vr=MIN;
    for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) CHMAX(vl,dat[l++]);  //左端を使いたくなるのはブロックが奇数の時
      if(r&1) CHMAX(vr,dat[--r]);  //右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return max(vl,vr);
  }
  U mi(int a,int b){//[a,b)のminを返す
    U vl=MAX,vr=MAX;
    for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) CHMIN(vl,dat[l++]);  //左端を使いたくなるのはブロックが奇数の時
      if(r&1) CHMIN(vr,dat[--r]);  //右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return min(vl,vr);
  }

  int IKA(T v,U x){
    int s=v.size();
    if(!s)return 0;
    if(v[0]>x)return 0;
    int l=-1,r=s;
    while(r-l>1){
      int m=(r+l)>>1;
      if(v[m]>x)r=m;
      else l=m;
    }
    return r;
  }

  int howmany(int a,int b,U x){
    T v=query(a,b);
    return IKA(v,x)-IKA(v,x-eps);
  }

  int G(vector<int> &d,int x){
    int l=-1,r=d.size();
    while(r-l>1){
      int mid=(r+l)>>1;
      (d[mid]>=x?r:l)=mid;
    }
    return d.size()-r;
  }

  int Q(int a,int b,int x){//[l,r)のx以上の個数
    int res=0;
    for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1) {
      if(l&1) res+=G(dat[l++],x);  //左端を使いたくなるのはブロックが奇数の時
      if(r&1) res+=G(dat[--r],x);  //右端〃偶数の時（開区間なのでr:奇数で反応）
    }
    return res;
  }

};
SegmentTree seg[26];//seg[i]のdat[j+n_]にはi+'a'がs[j]で最後に出た場所

signed main(){
  int n;cin>>n;
  vector<string> s(n);
  for(int i=0;i<n;i++)cin>>s[i];
  for(int i=0;i<n;i++)reverse(s[i].begin(),s[i].end());
  sort(s.begin(),s.end());
  for(int i=0;i<n;i++){
    vector<int> memo(26,-1);
    for(int j=0;j<s[i].size();j++)memo[s[i][j]-'a']=j;
    for(int j=0;j<26;j++)v[j].push_back(memo[j]);
  }
  for(int i=0;i<26;i++)seg[i].build(v[i]);
  for(int i=0;i<n;i++){
    ll a=1,b=1,c=1,d=1;
    hsh[i].push_back(PP(P(a,b),P(c,d)));
    for(int j=0;j<s[i].size();j++){
      (a*=s[i][j]*(j+1))%=MODA;
      (b*=s[i][j]+j+124)%=MODB;
      (c*=(s[i][j]*(j+7)))%=MODC;
      (d+=(s[i][j]*(j*j+5)%MODD))%=MODD;
      hsh[i].push_back(PP(P(++a,++b),P(++c,++d)));
    }
  }
  ll ans=0;
  for(int i=0;i<n;i++){
    int st=-1,r=i+1;//(st,i]がiと被る
    int L=s[i].size();
    while(r-st>1){
      int mid=(r+st)>>1;
      (hsh[mid].size()>=L&&hsh[mid][L-1]==hsh[i][L-1]?r:st)=mid;
    }
    int l=i-1,en=n;//[i,en)がiと被る
    while(en-l>1){
      int mid=(l+en)>>1;
      (hsh[mid].size()>=L&&hsh[mid][L-1]==hsh[i][L-1]?l:en)=mid;
    }
    int la=s[i].back()-'a';
    ans+=(ll)seg[la].Q(st+1,en,L-1)-1LL;
  }
  cout<<ans<<endl;
}


Measured memory_bytes: 1012304