#include <bits/stdc++.h>
using namespace std;
// #define int long long
typedef long long ll;
typedef pair<int, int> ii;
typedef pair<int, ii> iii;
template<class T>
bool minimize(T &a, const T &b) {
if (a > b) return a = b, true;
return false;
}
template<class T>
bool maximize(T &a, const T &b) {
if (a < b) return a = b, true;
return false;
}
#define FOR(i, a, b) for (int i = a; i <= (int)b; i++)
#define FORD(i, a, b) for (int i = a; i >= (int)b; i--)
#define MASK(i) (1LL << (i))
#define BIT(S, i) (((S) >> (i)) & 1)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define all(x) x.begin(), x.end()
const int N = 5e5 + 5;
const int mod = 1e9 + 7;
const int base = 311;
int n, m;
char a[255][255];
int sum[255][255][28];
bool okRow[255];
int hsh[255], pw[255];
int pre_hash[255], suf_hash[255], farLeft[255], farRight[255];
void init(void) {
cin >> n >> m;
FOR(i, 1, n) FOR(j, 1, m) cin >> a[i][j];
}
bool PalinRow(int id, int l, int r) {
int cntOdd = 0, cntEven = 0;
FOR(c, 0, 25) {
int cnt = sum[id][r][c] - sum[id][l - 1][c];
if (cnt & 1) cntOdd++;
else cntEven++;
}
if ((r - l + 1) % 2 == 0) return cntOdd == 0;
return cntOdd <= 1;
}
int getHashPre(int l, int r) {
return (pre_hash[r] - 1LL * pre_hash[l - 1] * pw[r - l + 1] % mod + 1LL * mod * mod) % mod;
}
int getHashSuf(int l, int r) {
return (suf_hash[l] - 1LL * suf_hash[r + 1] * pw[r - l + 1] % mod + 1LL * mod * mod) % mod;
}
void process(void) {
FOR(c, 0, 25) FOR(i, 1, n) FOR(j, 1, m) sum[i][j][c] = sum[i][j - 1][c] + ((a[i][j] - 'a') == c);
pw[0] = 1;
FOR(i, 1, n) pw[i] = 1LL * pw[i - 1] * base % mod;
int ans = 0;
FOR(col1, 1, m) FOR(col2, col1, m) {
FOR(row, 1, n) {
okRow[row] = PalinRow(row, col1, col2);
if(okRow[row] == 0) continue;
int _s = 0;
FOR(c, 0, 25) {
int tam = (sum[row][col2][c] - sum[row][col1 - 1][c]);
_s = 1LL * _s * base % mod + tam;
_s %= mod;
}
hsh[row] = _s;
}
FOR(row, 1, n) {
farLeft[row] = okRow[row] ? farLeft[row - 1] : row;
pre_hash[row] = 1LL * pre_hash[row - 1] * base % mod + hsh[row] % mod;
}
farRight[n + 1] = n + 1;
FORD(row, n, 1) {
farRight[row] = okRow[row] ? farRight[row + 1] : row;
suf_hash[row] = 1LL * suf_hash[row + 1] * base % mod + hsh[row] % mod;
}
if (1) {
FOR(i, 1, n) {
int l = 1, r = min(i - farLeft[i], farRight[i] - i);
int res = 0;
while (l <= r) {
int mid = (l + r) >> 1;
int hsh_left = getHashPre(i - mid + 1, i);
int hsh_right = getHashSuf(i, i + mid - 1);
if(hsh_left == hsh_right) {
res = mid, l = mid + 1;
} else r = mid - 1;
}
ans+= res;
}
}
if (1) {
FOR(i, 1, n) {
int l = 1, r = min(i - farLeft[i], farRight[i + 1] - (i + 1));
int res = 0;
while (l <= r) {
int mid = (l + r) >> 1;
int hsh_left = getHashPre(i - mid + 1, i);
int hsh_right = getHashSuf(i + 1, i + 1 + mid - 1);
if(hsh_left == hsh_right) {
res = mid, l = mid + 1;
} else r = mid - 1;
}
ans+= res;
}
}
}
cout << ans;
}
signed main(void) {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
#define taskname "kieuoanh"
if (fopen(taskname".inp", "r")) {
freopen(taskname".inp", "r", stdin);
freopen(taskname".out", "w", stdout);
}
init();
process();
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Ci8vICNkZWZpbmUgaW50IGxvbmcgbG9uZwp0eXBlZGVmIGxvbmcgbG9uZyBsbDsKdHlwZWRlZiBwYWlyPGludCwgaW50PiBpaTsKdHlwZWRlZiBwYWlyPGludCwgaWk+IGlpaTsKCnRlbXBsYXRlPGNsYXNzIFQ+CiAgICBib29sIG1pbmltaXplKFQgJmEsIGNvbnN0IFQgJmIpIHsKICAgICAgICBpZiAoYSA+IGIpIHJldHVybiBhID0gYiwgdHJ1ZTsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICB9Cgp0ZW1wbGF0ZTxjbGFzcyBUPgogICAgYm9vbCBtYXhpbWl6ZShUICZhLCBjb25zdCBUICZiKSB7CiAgICAgICAgaWYgKGEgPCBiKSByZXR1cm4gYSA9IGIsIHRydWU7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKI2RlZmluZSBGT1IoaSwgYSwgYikgZm9yIChpbnQgaSA9IGE7IGkgPD0gKGludCliOyBpKyspCiNkZWZpbmUgRk9SRChpLCBhLCBiKSBmb3IgKGludCBpID0gYTsgaSA+PSAoaW50KWI7IGktLSkKI2RlZmluZSBNQVNLKGkpICgxTEwgPDwgKGkpKQojZGVmaW5lIEJJVChTLCBpKSAoKChTKSA+PiAoaSkpICYgMSkKI2RlZmluZSBtcCBtYWtlX3BhaXIKI2RlZmluZSBwYiBwdXNoX2JhY2sKI2RlZmluZSBmaSBmaXJzdAojZGVmaW5lIHNlIHNlY29uZAojZGVmaW5lIGFsbCh4KSB4LmJlZ2luKCksIHguZW5kKCkKY29uc3QgaW50IE4gPSA1ZTUgKyA1Owpjb25zdCBpbnQgbW9kID0gMWU5ICsgNzsKY29uc3QgaW50IGJhc2UgPSAzMTE7CgppbnQgbiwgbTsKY2hhciBhWzI1NV1bMjU1XTsKaW50IHN1bVsyNTVdWzI1NV1bMjhdOwpib29sIG9rUm93WzI1NV07CmludCBoc2hbMjU1XSwgcHdbMjU1XTsKaW50IHByZV9oYXNoWzI1NV0sIHN1Zl9oYXNoWzI1NV0sIGZhckxlZnRbMjU1XSwgZmFyUmlnaHRbMjU1XTsKCnZvaWQgaW5pdCh2b2lkKSB7CgljaW4gPj4gbiA+PiBtOwoJRk9SKGksIDEsIG4pIEZPUihqLCAxLCBtKSBjaW4gPj4gYVtpXVtqXTsKfQoKYm9vbCBQYWxpblJvdyhpbnQgaWQsIGludCBsLCBpbnQgcikgewoJaW50IGNudE9kZCA9IDAsIGNudEV2ZW4gPSAwOwoJRk9SKGMsIDAsIDI1KSB7CgkJaW50IGNudCA9IHN1bVtpZF1bcl1bY10gLSBzdW1baWRdW2wgLSAxXVtjXTsKCQlpZiAoY250ICYgMSkgY250T2RkKys7CgkJZWxzZSBjbnRFdmVuKys7Cgl9CglpZiAoKHIgLSBsICsgMSkgJSAyID09IDApIHJldHVybiBjbnRPZGQgPT0gMDsKCXJldHVybiBjbnRPZGQgPD0gMTsKfQoKaW50IGdldEhhc2hQcmUoaW50IGwsIGludCByKSB7CglyZXR1cm4gKHByZV9oYXNoW3JdIC0gMUxMICogcHJlX2hhc2hbbCAtIDFdICogcHdbciAtIGwgKyAxXSAlIG1vZCArIDFMTCAqIG1vZCAqIG1vZCkgJSBtb2Q7Cn0KCmludCBnZXRIYXNoU3VmKGludCBsLCBpbnQgcikgewoJcmV0dXJuIChzdWZfaGFzaFtsXSAtIDFMTCAqIHN1Zl9oYXNoW3IgKyAxXSAqIHB3W3IgLSBsICsgMV0gJSBtb2QgKyAxTEwgKiBtb2QgKiBtb2QpICUgbW9kOwp9Cgp2b2lkIHByb2Nlc3Modm9pZCkgewoJRk9SKGMsIDAsIDI1KSBGT1IoaSwgMSwgbikgRk9SKGosIDEsIG0pIHN1bVtpXVtqXVtjXSA9IHN1bVtpXVtqIC0gMV1bY10gKyAoKGFbaV1bal0gLSAnYScpID09IGMpOwoJcHdbMF0gPSAxOwoJRk9SKGksIDEsIG4pIHB3W2ldID0gMUxMICogcHdbaSAtIDFdICogYmFzZSAlIG1vZDsKCWludCBhbnMgPSAwOwoJRk9SKGNvbDEsIDEsIG0pIEZPUihjb2wyLCBjb2wxLCBtKSB7CgkJRk9SKHJvdywgMSwgbikgewoJCQlva1Jvd1tyb3ddID0gUGFsaW5Sb3cocm93LCBjb2wxLCBjb2wyKTsKCQkJaWYob2tSb3dbcm93XSA9PSAwKSBjb250aW51ZTsKCQkJaW50IF9zID0gMDsKCQkJRk9SKGMsIDAsIDI1KSB7CgkJCQlpbnQgdGFtID0gKHN1bVtyb3ddW2NvbDJdW2NdIC0gc3VtW3Jvd11bY29sMSAtIDFdW2NdKTsKCQkJCV9zID0gMUxMICogX3MgKiBiYXNlICUgbW9kICsgdGFtOwoJCQkJX3MgJT0gbW9kOwoJCQl9CgkJCWhzaFtyb3ddID0gX3M7CgkJfQkJCgkJRk9SKHJvdywgMSwgbikgewoJCQlmYXJMZWZ0W3Jvd10gPSBva1Jvd1tyb3ddID8gZmFyTGVmdFtyb3cgLSAxXSA6IHJvdzsKCQkJcHJlX2hhc2hbcm93XSA9IDFMTCAqIHByZV9oYXNoW3JvdyAtIDFdICogYmFzZSAlIG1vZCArIGhzaFtyb3ddICUgbW9kOyAKCQl9CgkJZmFyUmlnaHRbbiArIDFdID0gbiArIDE7CgkJRk9SRChyb3csIG4sIDEpIHsKCQkJZmFyUmlnaHRbcm93XSA9IG9rUm93W3Jvd10gPyBmYXJSaWdodFtyb3cgKyAxXSA6IHJvdzsKCQkJc3VmX2hhc2hbcm93XSA9IDFMTCAqIHN1Zl9oYXNoW3JvdyArIDFdICogYmFzZSAlIG1vZCArIGhzaFtyb3ddICUgbW9kOwoJCX0JCgkJaWYgKDEpIHsKCQkJRk9SKGksIDEsIG4pIHsKCQkJCWludCBsID0gMSwgciA9IG1pbihpIC0gZmFyTGVmdFtpXSwgZmFyUmlnaHRbaV0gLSBpKTsKCQkJCWludCByZXMgPSAwOwoJCQkJd2hpbGUgKGwgPD0gcikgewoJCQkJCWludCBtaWQgPSAobCArIHIpID4+IDE7CgkJCQkJaW50IGhzaF9sZWZ0ID0gZ2V0SGFzaFByZShpIC0gbWlkICsgMSwgaSk7CgkJCQkJaW50IGhzaF9yaWdodCA9IGdldEhhc2hTdWYoaSwgaSArIG1pZCAtIDEpOwoJCQkJCWlmKGhzaF9sZWZ0ID09IGhzaF9yaWdodCkgewoJCQkJCQlyZXMgPSBtaWQsIGwgPSBtaWQgKyAxOwoJCQkJCX0gZWxzZSByID0gbWlkIC0gMTsKCQkJCX0KCQkJCWFucys9IHJlczsKCQkJfQoJCX0KCQlpZiAoMSkgewoJCQlGT1IoaSwgMSwgbikgewoJCQkJaW50IGwgPSAxLCByID0gbWluKGkgLSBmYXJMZWZ0W2ldLCBmYXJSaWdodFtpICsgMV0gLSAoaSArIDEpKTsKCQkJCWludCByZXMgPSAwOwoJCQkJd2hpbGUgKGwgPD0gcikgewoJCQkJCWludCBtaWQgPSAobCArIHIpID4+IDE7CgkJCQkJaW50IGhzaF9sZWZ0ID0gZ2V0SGFzaFByZShpIC0gbWlkICsgMSwgaSk7CgkJCQkJaW50IGhzaF9yaWdodCA9IGdldEhhc2hTdWYoaSArIDEsIGkgKyAxICsgbWlkIC0gMSk7CgkJCQkJaWYoaHNoX2xlZnQgPT0gaHNoX3JpZ2h0KSB7CgkJCQkJCXJlcyA9IG1pZCwgbCA9IG1pZCArIDE7CgkJCQkJfSBlbHNlIHIgPSBtaWQgLSAxOwoJCQkJfQoJCQkJYW5zKz0gcmVzOwoJCQl9CgkJfQoJfQkKCWNvdXQgPDwgYW5zOwp9CgpzaWduZWQgbWFpbih2b2lkKSB7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKICAgIGNpbi50aWUobnVsbHB0cik7CiAgICAjZGVmaW5lIHRhc2tuYW1lICJraWV1b2FuaCIKICAgIGlmIChmb3Blbih0YXNrbmFtZSIuaW5wIiwgInIiKSkgewogICAgICAgIGZyZW9wZW4odGFza25hbWUiLmlucCIsICJyIiwgc3RkaW4pOwogICAgICAgIGZyZW9wZW4odGFza25hbWUiLm91dCIsICJ3Iiwgc3Rkb3V0KTsKICAgIH0KICAgIGluaXQoKTsKICAgIHByb2Nlc3MoKTsKICAgIHJldHVybiAwOwp9