using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		
		var ca = new char[N][];
		for(int i=0;i<N;i++){
			ca[i] = S[i].ToCharArray();
			Array.Reverse(ca[i]); 
		}
		var Tr = new Trie();
		foreach(var xs in ca) Tr.Add(xs);
		
		int M = Tr.E.Count;
		int[][] cnt = new int[M][];
		for(int i=0;i<M;i++) cnt[i] = new int[26];
		for(int i=0;i<N;i++){
			int len = ca[i].Length;
			var hs = new HashSet<int>();
			int node = Tr.GetNode(ca[i], len);
			while(Tr.Parent[node] != -1){
				hs.Add(Tr.C[node] - 'a');
				foreach(var nc in hs) cnt[Tr.Parent[node]][nc]++;
				node = Tr.Parent[node];
			}
		}
		
		long ans = 0;
		for(int i=0;i<N;i++){
			int len = ca[i].Length;
			int pref = Tr.GetNode(ca[i], len - 1);
			ans += cnt[pref][S[i][0] - 'a'];
			ans -= 1; // myself
		}
		Console.WriteLine(ans);
		
	}
	int N;
	String[] S;
	public Sol(){
		N = ri();
		S = new String[N];
		for(int i=0;i<N;i++) S[i] = rs();
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}

class Trie{
	// 
	public List<int[]> E;
	public List<char> C;
	public List<long> Val;
	public List<int> Parent;
	public int Root;
	const int M = 26;


	public Trie(){
		E = new List<int[]>();
		C = new List<char>();
		Val = new List<long>();
		Parent = new List<int>();
		
		Root = 0;
		E.Add(new int[M]);
		C.Add('$');
		Val.Add(0);
		Parent.Add(-1);
	}
	public void Add(String s){
		Add(s, s.Length);
	}
	public void Add(String s, long v){
		// Add key: s, Value: v;
		int n = s.Length;
		int now = Root;
		for(int i=0;i<n;i++){
			int c = (int) (s[i] - 'a');
			if(E[now][c] <= 0){
				AddEdge(now, s[i]);
				now = E[now][c];
			} else {
				now = E[now][c];
			}
		}
		Val[now] = v;
	}
	public void Add(char[] s){
		Add(s, s.Length);
	}
	public void Add(char[] s, long v){
		// Add key: s, Value: v;
		int n = s.Length;
		int now = Root;
		for(int i=0;i<n;i++){
			int c = (int) (s[i] - 'a');
			if(E[now][c] <= 0){
				AddEdge(now, s[i]);
				now = E[now][c];
			} else {
				now = E[now][c];
			}
		}
		Val[now] = v;
	}
	void AddEdge(int now, char c){
		int nxt = E.Count;
		E.Add(new int[M]);
		C.Add(c);
		Val.Add(0);
		Parent.Add(now);
		E[now][c - 'a'] = nxt;
	}

	public bool Contains(String s){
		long v;
		return Contains(s, out v);
	}
	
	public int GetNode(char[] s, int length = -1){
		if(length == -1) length = s.Length;
		if(length == 0) return 0;
		int now = Root;
		for(int i=0;i<length;i++){
			now = E[now][s[i] - 'a'];
			if(now == 0){
				return -1;
			}
		}
		return now;
	}
	
	
	
	public bool Contains(String s, out long v){
		v = 0;
		if(s == ""){
			return false;
		}
		int n = s.Length;
		int now = Root;
		for(int i=0;i<n;i++){
			int c = (int) (s[i] - 'a');
			if(E[now][c] <= now){
				return false;
			}
			now = E[now][c];
		}
		v = Val[now];
		return v != 0;
	}

}

Measured memory_bytes: 329396