#ifndef LOCAL #pragma GCC optimize("O3") #endif #include using namespace std; #define sim template muu & operator<<( #define ris return *this #define eni(r) sim> typename enable_if <1 r sizeof(dud(0)),muu&>::type operator<<(c g) { sim> struct rge {c b,e ;}; sim> rge range(c i, c j) {return rge{i, j};} sim> auto dud(c *r)-> decltype(cerr << *r); sim> char dud(...); struct muu { #ifdef LOCAL stringstream a; ~muu() {cerr << a.str() << endl;} eni(<) a << boolalpha << g; ris;} eni(==) ris << range(begin(g), end(g));} sim, class m mor pair r) {ris << "(" << r.first << ", " << r.second << ")";} sim mor rge u) { a << "["; for (c i = u.b; i != u.e; ++i) *this << ", " + 2 * (i == u.b) << *i; ris << "]"; } #else sim mor const c&) {ris;} #endif muu & operator()(){ris;} }; #define debug (muu() << __FUNCTION__ << "#" << __LINE__ << ": ") #define imie(r) "[" #r ": " << (r) << "] " #define imask(r) "[" #r ": " << bitset<8 * sizeof(r)>(r) << "] " #define arr(a, i) "[" #a imie(i) ": " << a[i] << "] " #define arr2(a, i, j) "[" #a imie(i) imie(j) ": " << a[i][j] << "] " int n, m; const int N = 1007; short dp[107][N][N]; char tab[N][N]; char ntab[N][N]; long long wynik = 0; long long solve() { long long res = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { int c = tab[i][j] - 30; if (c == 0) continue; dp[c][i][j] = 1 + min(dp[c][i - 1][j], dp[c][i][j - 1]); if (dp[c][i][j] > 1) res += dp[c][i][j] - 1; } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { int c = tab[i][j] - 30; dp[c][i][j] = 0; } } return res; } int main() { scanf("%d %d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%s", tab[i] + 1); n = max(n, m); for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) { if (tab[i][j] == 0) tab[i][j] = (char) 30; } } for (int it = 0; it < 4; ++it) { for (int i = 1; i <= n; ++i) { for (int j = 1; j <= n; ++j) ntab[n - j + 1][i] = tab[i][j]; } for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) tab[i][j] = ntab[i][j]; wynik += solve(); } printf("%lld\n", wynik); return 0; }