#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << (x) << endl
using namespace std;
template <typename Functor>
struct fix_type
{
    Functor functor;
    template <typename... Args>
    decltype(auto) operator()(Args&&... args) const& { return functor(functor, std::forward<Args>(args)...); }
};
template <typename Functor>
fix_type<typename std::decay<Functor>::type> fix(Functor&& functor) { return {std::forward<Functor>(functor)}; }
template <typename T>
vector<T> Vec(int n, T v) { return vector<T>(n, v); }
template <class... Args>
auto Vec(int n, Args... args)
{
    auto val = Vec(args...);
    return vector<decltype(val)>(n, move(val));
}

int main()
{
    while (true) {
        int H, W;
        cin >> H >> W;
        if (H == 0 and W == 0) { break; }
        auto C = Vec(H, W, char(0));
        auto I = Vec(H, W, -1);
        using P = pair<int, int>;
        auto in = [&](const int y, const int x) { return y >= 0 and y < H and x >= 0 and x < W and C[y][x] != '#'; };
        vector<P> pos[26]{}, POS[26]{};
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                cin >> C[i][j];
                if (islower(C[i][j])) {
                    const int c = C[i][j] - 'a';
                    pos[c].push_back({i, j});
                    I[i][j] = pos[c].size() - 1;
                } else if (isupper(C[i][j])) {
                    const int c = C[i][j] - 'A';
                    POS[c].push_back({i, j});
                    I[i][j] = POS[c].size() - 1;
                }
            }
        }
        auto bfs = [&](const int y, const int x) {
            auto used = Vec(H, W, false);
            queue<P> q;
            q.push({y, x}), used[y][x] = true;
            while (not q.empty()) {
                const int y = q.front().first, x = q.front().second;
                q.pop();
                if (in(y + 1, x) and not used[y + 1][x]) { q.push({y + 1, x}), used[y + 1][x] = true; }
                if (in(y, x + 1) and not used[y][x + 1]) { q.push({y, x + 1}), used[y][x + 1] = true; }
            }
            return used;
        };
        if (not bfs(0, 0)[H - 1][W - 1]) {
            cout << -1 << endl;
            continue;
        }
        vector<vector<bool>> ok[26];
        for (int i = 0; i < 26; i++) {
            const int S = pos[i].size(), T = POS[i].size();
            ok[i] = Vec(S, T, false);
            for (int j = 0; j < S; j++) {
                const auto used = bfs(pos[i][j].first, pos[i][j].second);
                for (int k = 0; k < T; k++) { ok[i][j][k] = used[POS[i][k].first][POS[i][k].second]; }
            }
        }
        auto memo = Vec(H, W, H, W, -1);
        constexpr int INF = 1 << 30;
        auto solve = fix([&](auto&& self, const int y1, const int x1, const int y2, const int x2) -> int {
            if (not in(y1, x1) or not in(y2, x2) or y2 < y1 or x2 < x1) { return -INF; }
            if (y1 == y2 and x1 == x2) { return memo[y1][x1][y2][x2] = 0; }
            if (memo[y1][x1][y2][x2] != -1) { return memo[y1][x1][y2][x2]; }
            int ans = max(self(self, y1 + 1, x1, y2, x2), self(self, y1, x1 + 1, y2, x2));
            if (islower(C[y1][x1]) == 0) { return memo[y1][x1][y2][x2] = ans; }
            const int c = C[y1][x1] - 'a', ind = I[y1][x1];
            for (int j = 0; j < POS[c].size(); j++) {
                if (ok[c][ind][j]) {
                    const int D = abs(y1 - POS[c][j].first) + abs(x1 - POS[c][j].second);
                    const int after = self(self, POS[c][j].first, POS[c][j].second, y2, x2);
                    const int before = D == 1 ? 0 : max({self(self, y1 + 1, x1, POS[c][j].first - 1, POS[c][j].second), self(self, y1, x1 + 1, POS[c][j].first - 1, POS[c][j].second), self(self, y1 + 1, x1, POS[c][j].first, POS[c][j].second - 1), self(self, y1, x1 + 1, POS[c][j].first, POS[c][j].second - 1)});
                    ans = max(ans, before + after + 1);
                }
            }
            return memo[y1][x1][y2][x2] = ans;
        });
        cout << solve(0, 0, H - 1, W - 1) << endl;
    }
    return 0;
}



Measured memory_bytes: 31840