#include <bits/stdc++.h>
using namespace std;
#define int long long   // <-----!!!!!!!!!!!!!!!!!!!

#define rep(i,n) for (int i=0;i<(n);i++)
#define rep2(i,a,b) for (int i=(a);i<(b);i++)
#define rrep(i,n) for (int i=(n)-1;i>=0;i--)
#define rrep2(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define all(a) (a).begin(),(a).end()

typedef long long ll;
typedef pair<int, int> Pii;
typedef tuple<int, int, int> TUPLE;
typedef vector<int> V;
typedef vector<V> VV;
typedef vector<VV> VVV;
typedef vector<vector<int>> Graph;
const int inf = 1e9;
const int mod = 1e9 + 7;

enum { X, Y, CHAR };
typedef vector<int> Tile;

int H, W;
vector<string> s;

// N, E, S, W
const int dx[4] = {-1, 0,  1,  0};
const int dy[4] = { 0, 1,  0, -1};

inline bool inside(int x, int y) {
    return 0 <= x && x < H && 0 <= y && y < W;
}

Tile findNearestTile(int x, int y, int k) {
    if (!inside(x, y) || s[x][y] == '#') return Tile{-1, -1, -1};
    if (isalpha(s[x][y])) return Tile{x, y, s[x][y] - 'A'};
    return findNearestTile(x + dx[k], y + dy[k], k);
}

bool hit(int sx, int sy) {
    if (s[sx][sy] == '#') return false;
    if (isalpha(s[sx][sy])) {
        rep(k, 4) {
            int nx = sx + dx[k], ny = sy + dy[k];
            if (!inside(nx, ny)) continue;
            if (s[sx][sy] == s[nx][ny]) {
                s[sx][sy] = '.';
                s[nx][ny] = '.';
                return true;
            }
        }
        return false;
    }

    rep(start, 4) {
        Tile tile1{-1, -1, -1};
        rep(k, 4) {
            Tile tile2 = findNearestTile(sx, sy, (k + start) % 4);
            if (tile2[CHAR] == -1) {
                continue;
            } else if (tile1[CHAR] == -1) {
                tile1 = tile2;
            } else if (tile1[CHAR] == tile2[CHAR]) {
                s[tile1[X]][tile1[Y]] = '.';
                s[tile2[X]][tile2[Y]] = '.';
                return true;
            }
        }
    }
    return false;
}

bool search() {
    rep(i, H) {
        rep(j, W) {
            if (hit(i, j)) {
                return true;
            }
        }
    }
    return false;
}

bool checkCompress(string line) {
    for (const auto& c : line) {
        if (c != '.') return false;
    }
    return true;
}

void compress(vector<string> &s) {
    for (int i = 0; i < s.size(); ) {
        if (checkCompress(s[i])) {
            s.erase(s.begin() + i);
        } else {
            i++;
        }
    }
}

void rot(vector<string> &s) {
    vector<string> t(s[0].size(), "");
    rep(i, s.size()) rep(j, s[0].size()) {
        t[j] += s[i][j];
    }
    s = t;
}

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    cin >> H >> W;
    s.resize(H);
    rep(i, H) cin >> s[i];

    rep(x, H) {
        rep(y, W) {
            rep(k, 4) {
                int nx = x + dx[k], ny = y + dy[k];
                if (!inside(nx, ny)) continue;
                if (isalpha(s[x][y]) && s[x][y] == s[nx][ny]) {
                    s[x][y] = '#';
                    s[nx][ny] = '#';
                }
            }
        }
    }

    compress(s);
    if (s.empty()) {
        cout << 0 << endl;
        return 0;
    }
    rot(s);
    compress(s);
    rot(s);

    H = s.size(), W = s[0].size();

    int ans = 0;
    while (search()) {
        ans += 2;
    }

    cout << ans << endl;

}

Measured memory_bytes: 3448