#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization("unroll-loops")
using namespace std;
long long max(long long a, long long b) {
  if (a < b) return b;
  return a;
}
long long min(long long a, long long b) {
  if (a < b) return a;
  return b;
}
long long X[] = {-1, 1, 0, 0};
long long Y[] = {0, 0, -1, 1};
long long XX[] = {-1, 1, 0, 0, -1, 1, -1, 1};
long long YY[] = {0, 0, -1, 1, -1, 1, 1, -1};
void solve() {
  unordered_map<string, vector<long long> > m;
  long long n, k;
  cin >> n >> k;
  string s[n];
  for (int i = 0; i < n; i++) {
    cin >> s[i];
    m[s[i]].push_back(i);
  }
  if (n <= 2) {
    cout << 0;
    return;
  }
  long long ans = 0;
  for (int i = 0; i < n - 1; i++) {
    for (int j = i + 1; j < n; j++) {
      string req = "";
      for (int q = 0; q < k; q++) {
        if (s[i][q] == s[j][q]) {
          req.insert(req.end(), s[i][q]);
        } else {
          char a = s[i][q], b = s[j][q];
          if (a != 'S' && b != 'S')
            req.insert(req.end(), 'S');
          else if (a != 'E' && b != 'E')
            req.insert(req.end(), 'E');
          else if (a != 'T' && b != 'T')
            req.insert(req.end(), 'T');
        }
      }
      vector<long long> vec = m[req];
      for (int q = 0; q < vec.size(); q++) {
        long long ind = vec[q];
        if (ind > j) ans++;
      }
    }
  }
  cout << ans;
}
int32_t main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  solve();
}
