Sonya had a birthday recently. She was presented with the matrix of size n× m and consist of lowercase Latin letters. We assume that the rows are numbered by integers from 1 to n from bottom to top, and the columns are numbered from 1 to m from left to right. 

Let's call a submatrix (i_1, j_1, i_2, j_2) (1≤ i_1≤ i_2≤ n; 1≤ j_1≤ j_2≤ m) elements a_{ij} of this matrix, such that i_1≤ i≤ i_2 and j_1≤ j≤ j_2. Sonya states that a submatrix is beautiful if we can independently reorder the characters in each row (not in column) so that all rows and columns of this submatrix form palidroms. 

Let's recall that a string is called palindrome if it reads the same from left to right and from right to left. For example, strings abacaba, bcaacb, a are palindromes while strings abca, acbba, ab are not.

Help Sonya to find the number of beautiful submatrixes. Submatrixes are different if there is an element that belongs to only one submatrix.

Input

The first line contains two integers n and m (1≤ n, m≤ 250) — the matrix dimensions.

Each of the next n lines contains m lowercase Latin letters.

Output

Print one integer — the number of beautiful submatrixes.

Examples

Input


1 3
aba


Output


4

Input


2 3
aca
aac


Output


11

Input


3 5
accac
aaaba
cccaa


Output


43

Note

In the first example, the following submatrixes are beautiful: ((1, 1), (1, 1)); ((1, 2), (1, 2)); ((1, 3), (1, 3)); ((1, 1), (1, 3)).

In the second example, all submatrixes that consist of one element and the following are beautiful: ((1, 1), (2, 1)); ((1, 1), (1, 3)); ((2, 1), (2, 3)); ((1, 1), (2, 3)); ((2, 1), (2, 2)).

Some of the beautiful submatrixes are: ((1, 1), (1, 5)); ((1, 2), (3, 4)); ((1, 1), (3, 5)).

The submatrix ((1, 1), (3, 5)) is beautiful since it can be reordered as:
    
    
      
    accca  
    aabaa  
    accca  
    

In such a matrix every row and every column form palindromes.
#include <bits/stdc++.h>
#pragma GGC optimize("Ofast")
using namespace std;
template <typename T>
void dprintln(const T &t) {
  cout << t << endl;
}
template <typename T, typename... Args>
void dprintln(const T &t, const Args &...rest) {
  cout << t << ' ';
  dprintln(rest...);
}
template <typename T>
void println(const T &t) {
  cout << t << '\n';
}
template <typename T, typename... Args>
void println(const T &t, const Args &...rest) {
  cout << t << ' ';
  println(rest...);
}
template <typename T>
void print(const T &t) {
  cout << t << ' ';
}
template <typename T, typename... Args>
void print(const T &t, const Args &...rest) {
  cout << t << ' ';
  print(rest...);
}
template <class T>
void scan(T &t) {
  cin >> t;
}
template <class T, class... Args>
void scan(T &a, Args &...rest) {
  cin >> a;
  scan(rest...);
}
using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;
using pii = pair<int, int>;
using vb = vector<bool>;
using vpii = vector<pii>;
auto bet = [](const ll x, const ll y, const ll i) { return x <= i && i <= y; };
inline int h_bit(unsigned int x) { return 31 - __builtin_clz(x); }
inline int h_bitll(unsigned long long x) { return 63 - __builtin_clzll(x); }
template <typename T>
struct bit {
  vector<T> a;
  explicit bit(int n, int v = 0) {
    a.resize(n + 1);
    if (v != 0) {
      for (int i = 1; i <= n; ++i) a[i] = v;
    }
  }
  T sum(T x) {
    T res = 0;
    while (x) {
      res += a[x];
      x -= x & -x;
    }
    return res;
  }
  T sum(int l, int r) {
    if (l > r) return 0;
    return sum(r) - sum(l - 1);
  }
  void add(int x, T v) {
    while (x < a.size()) {
      a[x] += v;
      x += x & -x;
    }
  }
  void clear() { fill(a.begin(), a.end(), 0); }
};
vi get_prime(int n) {
  vi minp(n + 1), p;
  for (int i = 2; i <= n; i++) {
    if (!minp[i]) {
      minp[i] = i;
      p.push_back(i);
    }
    for (auto &x : p) {
      if (x <= minp[i] && x * i <= n)
        minp[x * i] = x;
      else
        break;
    }
  }
  return p;
}
const int mod = 998244353;
inline void add_mod(ll &x, const ll &y) {
  x += y;
  if (x >= mod) x -= mod;
}
inline ll submod(ll x, ll y) { return x >= y ? x - y : x - y + mod; }
void sub_mod(ll &x, const ll y) {
  x -= y;
  if (x < 0) x += mod;
}
template <typename T>
using vv = vector<vector<T>>;
template <typename T1, typename T2 = T1>
using vp = vector<pair<T1, T2>>;
template <typename T, int n>
using va = vector<array<T, n>>;
struct UF {
  vi par;
  explicit UF(int n) {
    par.assign(n + 1, 0);
    for (int i = (1); i < (n + 1); ++i) par[i] = i;
  }
  int find(int x) { return x == par[x] ? x : par[x] = find(par[x]); }
  void unite(int x, int y) { par[find(x)] = find(y); }
};
vi get_popcnt(int n) {
  vi res(n + 1);
  for (int i = (0); i < (n); ++i) {
    if (i * 2 <= n) res[i * 2] = res[i];
    if ((i & 1) == 0) res[i + 1] = res[i] + 1;
  }
  return res;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  int n, m;
  scan(n, m);
  vector<string> a(n);
  for (auto &s : a) cin >> s;
  vi h0(n), h1(n);
  auto manacher = [&h0, &h1](const vi &s, int l, int r) {
    int ans = 0;
    for (int border = l, mid = l, i = l; i < r; ++i) {
      int radius = border > i ? min(h1[2 * mid - i], border - i) : 0;
      while (i - radius >= l && i + radius < r &&
             s[i - radius] == s[i + radius])
        ++radius;
      if (border < radius + i) {
        border = radius + i;
        mid = i;
      }
      h1[i] = radius;
      ans += radius;
    }
    for (int border = l, mid = l, i = l; i < r; ++i) {
      int radius = border > i ? min(h0[2 * mid - i], border - i) : 0;
      while (i - radius - 1 >= l && i + radius < r &&
             s[i - radius - 1] == s[i + radius])
        ++radius;
      if (border < i + radius) {
        border = radius + i;
        mid = i;
      }
      h0[i] = radius;
      ans += radius;
    }
    return ans;
  };
  vi p(26);
  for (int i = 0, t = 1, base = 131; i < 26; ++i) {
    p[i] = t;
    t = 1LL * t * base % mod;
  }
  ll ans = 0;
  for (int l = (0); l < (m); ++l) {
    vi hash(n);
    vv<int> cnt(n, vi(26));
    vi n_odd(n);
    for (int r = (l); r < (m); ++r) {
      for (int i = 0; i < n; ++i) {
        int t = a[i][r] - 'a';
        (hash[i] += p[t]) %= mod;
        cnt[i][t]++;
        if (cnt[i][t] & 1)
          n_odd[i]++;
        else
          n_odd[i]--;
      }
      for (int i = (0); i < (n); ++i) {
        int j = i;
        while (i < n && n_odd[i] <= 1) {
          ++i;
        }
        ans += manacher(hash, j, i);
      }
    }
  }
  println(ans);
  return 0;
}
