#include <bits/stdc++.h>

using namespace std;
#define rep(i,n) for (int i = 0; i < (n); ++i)
using ll = long long;
using Graph = vector<vector<int>>;
using pint = pair<int, int>;
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
const int IINF = 1LL << 29;
const long long INF = 1LL << 60;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

int main() {
    cout << setprecision(15) << fixed;
    int H, W; cin >> H >> W;
    vector<string> A(H);
    pint S, G;
    vector<vector<pint>> rec(26, vector<pint>());
    rep(i, H) cin >> A[i];
    rep(i, H) {
        rep(j, W) {
            char c = A[i][j];
            if (c == 'S') S = {i, j};
            if (c == 'G') G = {i, j};
            if (c >= 'a' && c <= 'z') rec[(c - 'a')].push_back({i, j});
        }
    }
    queue<pint> que;
    que.push(S);
    vector<vector<int>> dist(H, vector<int>(W, -1));
    dist[S.first][S.second] = 0;
    vector<bool> used(26, false);
    while (!que.empty()) {
        auto [y, x] = que.front(); que.pop();
        if (A[y][x] >= 'a' && A[y][x] <= 'z') {
            int c = A[y][x] - 'a';
            if (!used[c]) {
                for (auto [ny, nx] : rec[c]) {
                    if (dist[ny][nx] == -1) {
                        que.push({ny, nx});
                        dist[ny][nx] = dist[y][x] + 1;
                    }
                }
            }
            used[c] = true;
        }
        rep(i, 4) {
            int ny = y + dy[i];
            int nx = x + dx[i];
            if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue;
            if (A[ny][nx] == '#') continue;
            if (dist[ny][nx] == -1) {
                que.push({ny, nx});
                dist[ny][nx] = dist[y][x] + 1;
            }

        }
    }
    cout << dist[G.first][G.second] << endl;
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define sz(x) ((int) (x).size())
typedef pair<int, int> pii;
typedef double ll;
const int maxn = 2000 + 5;
template<class T> void print(T & x){ cout << x; }
template<class T,class U> void print(pair<T,U> & p){cout << "("; print(p.first); cout << ", "; print(p.second); cout << ")"; }
template<class T> void print(vector<T> & v) {
    cout << "{";
    if (sz(v)) print(v[0]);
    for (int i = 1; i < sz(v); i++) cout << ", ", print(v[i]);
    cout << "}\n";
}

struct Dijkstra {
    
    int tot, n, m; 
    struct Node {
        int nxt, v; ll len;
    };
    Node* edges;
    int* head;
    ll* d;

    Dijkstra(int tn, int tm) {
        n = tn, m = tm; tot = 0;
        head = new int[tn+1]; fill(head+1, head+n+1, -1);
        edges = new Node [tm+1]; 
        d = new ll [tn+1]; fill(d+1, d+n+1, 1e18);
    }
    ~Dijkstra() {
        if (head) { delete [] head; head = NULL; }
        if (edges) { delete [] edges; edges = NULL; }
        if (d) { delete [] d; d = NULL; }   
    }

    void addedge(int x, int y, ll val) {
        edges[++tot] = {head[x], y, val};
        head[x] = tot;
    }

    void calc(int s) {
        priority_queue<pair<ll, int>, vector<pair<ll, int>>, greater<pair<ll, int>>> Q;
        vector<bool> done(n+1);
        d[s] = 0;
        Q.push({d[s], s});

        while(!Q.empty()) {
            int x = Q.top().second; Q.pop();
            if (done[x]) continue; else done[x] = true;
            for (int i = head[x]; ~i; i = edges[i].nxt) {
                int v = edges[i].v; ll len = edges[i].len;
                if (d[v] > d[x] + len) {
                    d[v] = d[x] + len;
                    Q.push({d[v], v});
                }
            }
        }
    }
};

int n, m;
char A[maxn][maxn];

const int dx[] = {-1, 1, 0, 0};
const int dy[] = {0 ,0, 1, -1};

inline int ind(int x, int y) {
    return x * m + y;
}

inline int indc(int c) {
    return (n+1)*(m+1)+c; 
}   

vector<pii> dic[26];

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    pii st, ed;
    for (int i = 1;i <= n; ++i) {
        for (int j = 1;j <= m; ++j) {
            cin >> A[i][j];
            if ('a' <= A[i][j] && A[i][j] <= 'z') dic[A[i][j] - 'a'].push_back({i, j});
            if (A[i][j] == 'S') st = {i, j};
            if (A[i][j] == 'G') ed = {i, j};
        }
    }
    Dijkstra dij((n+1)*(m+1)+30, (n+1)*(m+1)*40);
    for (int i = 1;i <= n; ++i) {
        for (int j = 1;j <= m; ++j) {
            if (A[i][j] == '#') continue;
            for (int k = 0;k < 4; ++k) {
                int nx = i + dx[k];
                int ny = j + dy[k];
                if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
                if (A[nx][ny] == '#') continue;
                dij.addedge(ind(i, j), ind(nx, ny), 1);
            }
        }
    }
 
    for (int c = 0;c < 26; ++c) {
        for (auto [x, y] : dic[c]) {
            dij.addedge(ind(x, y), indc(c), 0.5);
            dij.addedge(indc(c), ind(x,y), 0.5);
        }
    }
    dij.calc(ind(st.first, st.second));
    // for (int i = 1;i <= n; ++i) {
    //     for (int j = 1;j <= m; ++j) {
    //         cout << dij.d[ind(i,j)] <<" ";
    //     }cout << endl;
    // }
    
    
    if (dij.d[ind(ed.first, ed.second)] > 1e9) cout << -1 << endl;
    else cout << (long long)(dij.d[ind(ed.first, ed.second)] + 0.5) << endl;
    return 0;
}