#include <bits/stdc++.h>
using namespace std;
using Id = int;
bool Valid(const vector<vector<int>> &count, int left, int right) {
  int odd_count = 0;
  for (int i = 0; i < 26; i += 1) {
    int curr_count = count[right][i] - (left > 0 ? count[left - 1][i] : 0);
    odd_count += (curr_count % 2);
  }
  return odd_count < 2;
}
int64_t TotalOdd(const vector<Id> &ids, const vector<bool> &valid) {
  vector<int> range(ids.size(), 1);
  int left = 0;
  int right = -1;
  int64_t total = 0;
  for (int i = 0; i < (int)ids.size(); i += 1) {
    if (!valid[i]) {
      continue;
    }
    if (i <= right) {
      range[i] = min(range[left + right - i], right - i + 1);
    }
    while (0 <= i - range[i] && i + range[i] < (int)ids.size() &&
           ids[i - range[i]] == ids[i + range[i]]) {
      if (!valid[i - range[i]] || !valid[i + range[i]]) {
        break;
      }
      range[i] += 1;
    }
    if (i + range[i] - 1 > right) {
      left = i - range[i] + 1;
      right = i + range[i] - 1;
    }
    total += range[i];
  }
  return total;
}
int64_t TotalEven(const vector<Id> &ids, const vector<bool> &valid) {
  vector<int> range(ids.size(), 0);
  int left = 0;
  int right = -1;
  int64_t total = 0;
  for (int i = 0; i < (int)ids.size(); i += 1) {
    if (!valid[i]) {
      continue;
    }
    if (i <= right) {
      range[i] = min(range[left + right - i + 1], right - i + 1);
    }
    while (0 <= i - range[i] - 1 && i + range[i] < (int)ids.size() &&
           ids[i - range[i] - 1] == ids[i + range[i]]) {
      if (!valid[i - range[i] - 1] || !valid[i + range[i]]) {
        break;
      }
      range[i] += 1;
    }
    if (i + range[i] - 1 > right) {
      left = i - range[i];
      right = i + range[i] - 1;
    }
    total += range[i];
  }
  return total;
}
int64_t CountPalindromes(const vector<Id> &ids, const vector<bool> &valid) {
  return TotalOdd(ids, valid) + TotalEven(ids, valid);
}
Id MakeId(const vector<vector<int>> &count, int left, int right) {
  static constexpr int kBase = 2000003543;
  Id id = 0;
  for (int i = 0; i < 26; i += 1) {
    int curr_count = count[right][i] - (left > 0 ? count[left - 1][i] : 0);
    id = 1LL * id * kBase + curr_count;
  }
  return id;
}
int64_t CountSubmatrices(const vector<string> &mat) {
  vector<vector<vector<int>>> count(mat.size());
  for (size_t i = 0; i < mat.size(); i += 1) {
    count[i].assign(mat[i].size(), vector<int>(26, 0));
    count[i][0][mat[i][0] - 'a'] = 1;
    for (size_t j = 1; j < mat[i].size(); j += 1) {
      count[i][j] = count[i][j - 1];
      count[i][j][mat[i][j] - 'a'] += 1;
    }
  }
  int64_t submatrices = 0;
  for (size_t left = 0; left < mat[0].size(); left += 1) {
    for (size_t right = left; right < mat[0].size(); right += 1) {
      vector<Id> ids(mat.size());
      vector<bool> valid(mat.size());
      for (size_t row = 0; row < mat.size(); row += 1) {
        ids[row] = MakeId(count[row], left, right);
        valid[row] = Valid(count[row], left, right);
      }
      submatrices += CountPalindromes(ids, valid);
    }
  }
  return submatrices;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int rows, cols;
  cin >> rows >> cols;
  cin.get();
  vector<string> mat(rows);
  for (auto &row : mat) {
    getline(cin, row);
  }
  auto res = CountSubmatrices(mat);
  cout << res << "\n";
  return 0;
}
