#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
typedef pair <int, int> pin;

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

int n, m, f[N][N];
char s[N][N];
bool vis[N][N];
vector <pin> vec[26];

template <typename T>
inline void read(T &X) {
    char ch = 0; T op = 1; 
    for (X = 0; ch > '9' || ch < '0'; ch = getchar())
        if (ch == '-') op = -1;
    for (; ch >= '0' && ch <= '9'; ch = getchar())
        X = (X * 10) + ch - '0';
    X *= op;
}

inline bool valid(int x, int y) {
    return x >= 1 && x <= n && y >= 1 && y <= m && s[x][y] != '#';
}

queue <pin> q;
inline int solve(int sx, int sy, int ex, int ey) {
    q.push(pin(sx, sy));
    vis[sx][sy] = 1;
    for (; !q.empty(); ) {
        pin now = q.front(); q.pop();
        int x = now.first, y = now.second;
        if (x == ex && y == ey) return f[x][y];
        for (int i = 0; i < 4; i++) {
            int tox = x + dx[i], toy = y + dy[i];
            if (valid(tox, toy) && !vis[tox][toy]) {
                f[tox][toy] = f[x][y] + 1;
                vis[tox][toy] = 1;
                q.push(pin(tox, toy));
            }
        }
        if (s[x][y] >= 'a' && s[x][y] <= 'z') {
            int c = s[x][y] - 'a';
            for (int i = 0; i < vec[c].size(); i++) {
                int tox = vec[c][i].first, toy = vec[c][i].second;
                if (vis[tox][toy]) continue;
                vis[tox][toy] = 1;
                f[tox][toy] = f[x][y] + 1;
                q.push(pin(tox, toy));
            }
        }
    }
    return -1;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("sample.in", "r", stdin);
#endif

    read(n), read(m);
    for (int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
    int sx, sy, ex, ey;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            if (s[i][j] == 'G') ex = i, ey = j;
            if (s[i][j] == 'S') sx = i, sy = j;
            if (s[i][j] >= 'a' && s[i][j] <= 'z') vec[s[i][j] - 'a'].push_back(pin(i, j));
        }
    printf("%d\n", solve(sx, sy, ex, ey));
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i = (a); i < (b); i++)
#define drep(i,b,a) for(int i = (b)-1; i >= (a); i--)
#define bit(n) (1LL << (n))
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define SORT(v) sort(v.begin(),v.end());
#define RSORT(v) sort(v.rbegin(),v.rend());
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<double> vd;
typedef vector<bool> vb;
typedef vector<char> vc;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef vector<vd> vvd;
typedef vector<vb> vvb;
typedef vector<vc> vvc;
const int inf = 1 << 30; const ll infl = 1LL << 60; const double PI = acos(-1.0);
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; }
template<class T> inline bool  odd(T x) { return x & 1; }
template<class T> inline bool even(T x) { return !(x & 1); }
template<typename A, size_t N, typename T> 
void Fill(A (&array)[N], const T &val) {
    std::fill( (T*)array, (T*)(array+N), val );
}
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << endl; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }
//----------------------------------------------------------------------------------------------

using P = pair<int,int>;
int dist[2020][2020];
const int di[] = {1, 0,-1, 0};
const int dj[] = {0, 1, 0,-1};

int main() 
{
    int h,w;
    cin >> h >> w;
    vector<string> g(h);
    rep(i,0,h) cin >> g[i];

    vector<vector<P>> table(26);
    vector<bool> used(26);
    int si,sj,gi,gj;
    rep(i,0,h) rep(j,0,w) {
        char c = g[i][j];
        if('a' <= c && c <= 'z') table[c-'a'].emplace_back(i,j);
        if(c == 'S') si = i, sj = j;
        if(c == 'G') gi = i, gj = j;
    }
    
    Fill(dist, -1);
    queue<P> que;
    dist[si][sj] = 0;
    que.emplace(si,sj);
    while(!que.empty()) {
        auto [ci,cj] = que.front(); que.pop();
        rep(k,0,4) {
            int ni = ci + di[k];
            int nj = cj + dj[k];
            if(ni < 0 || ni >= h || nj < 0 || nj >= w) continue;
            if(g[ni][nj] == '#' || dist[ni][nj] != -1) continue;
            dist[ni][nj] = dist[ci][cj] + 1;
            que.emplace(ni,nj);
        }
        char c = g[ci][cj];
        if('a' <= c && c <= 'z') {
            if(used[c-'a']) continue;
            for(auto [ni,nj] : table[c-'a']) {
                if(ni < 0 || ni >= h || nj < 0 || nj >= w) continue;
                if(g[ni][nj] == '#' || dist[ni][nj] != -1) continue;
                dist[ni][nj] = dist[ci][cj] + 1;
                que.emplace(ni,nj);
            }
            used[c-'a'] = true;
        }
    }
    cout << dist[gi][gj] << endl;
    return 0;
}