#include <bits/stdc++.h>
using namespace std;
template <typename T>
string to_string(const vector<T>& vc, int w) {
  if (vc.empty()) return "";
  if (w + 1 == vc.size()) return to_string(vc[w]);
  return to_string(vc[w]) + "," + to_string(vc, w + 1);
}
template <typename T>
string to_string(const vector<T>& vc) {
  return "{" + to_string(vc, 0) + "}";
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
class DebugStream {
} LOG;
template <typename T>
DebugStream& operator<<(DebugStream& s, const T&) {
  return s;
}
mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
const int maxN = 2e3 + 9, maxV = 1e6 + 9, MOD = 1e9 + 7, SQ = 335, lg = 20,
          bs = 29;
string mat[maxN];
int n, m, vl[maxN][maxN];
int dr[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
bool ins(int x, int y) { return x >= 0 && y >= 0 && x < n && y < m; }
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> n >> m;
  for (int i = 0; i < n; i++) cin >> mat[i];
  vector<pair<long long, long long> > arr;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      bool has = 0;
      for (int k = 0; k < 4; k++) {
        int x = i + dr[k][0], y = j + dr[k][1];
        if (!ins(x, y) || mat[i][j] != mat[x][y]) has = 1;
      }
      if (has) arr.emplace_back(i, j), vl[i][j] = 1;
    }
  }
  while (arr.size()) {
    vector<pair<long long, long long> > nxt;
    for (auto el : arr) {
      for (int k = 0; k < 4; k++) {
        int x = el.first + dr[k][0], y = el.second + dr[k][1];
        if (ins(x, y) && !vl[x][y]) {
          vl[x][y] = vl[el.first][el.second] + 1;
          nxt.emplace_back(x, y);
        }
      }
    }
    arr = nxt;
  }
  int ans = 0;
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) ans += vl[i][j];
  cout << ans << '\n';
}
