#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
#define pb push_back

int solve()
{
    int h, w, di[4] = {0, 1, 0, -1}, dj[4] = {1, 0, -1, 0};
    char c;
    cin >> h >> w;
    vector<vector<pair<int, int>>> alphabet(26);
    vector<vector<char>> grid(h, vector<char>(w));
    vector<vector<bool>> vis(h, vector<bool>(w));
    pair<int, int> cur = {0, 0};
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            cin >> grid[i][j];
            if (grid[i][j] == 'S')
            {
                cur.first = i;
                cur.second = j;
            }
            else if (grid[i][j] >= 'a' && grid[i][j] <= 'z')
            {
                alphabet[grid[i][j] - 'a'].pb({i, j});
            }
        }
    }
    int time = 1;
    queue<pair<int, int>> q;
    q.push(cur);
    vis[cur.first][cur.second] = true;
    while (!q.empty())
    {
        int len = q.size();
        while (len-- > 0)
        {
            pair<int, int> from = q.front();
            q.pop();
            for (int dir = 0; dir < 4; dir++)
            {
                int i = from.first + di[dir], j = from.second + dj[dir];
                if (i >= 0 && i < h && j >= 0 && j < w && grid[i][j] != '#' && !vis[i][j])
                {
                    if (grid[i][j] == 'G')
                        return time;
                    vis[i][j] = true;
                    q.push({i, j});
                }
            }
            if (grid[from.first][from.second] >= 'a' && grid[from.first][from.second] <= 'z')
            {
                for (pair<int, int> tel : alphabet[grid[from.first][from.second] - 'a'])
                {
                    if (grid[tel.first][tel.second] == 'G')
                        return time;
                    if (vis[tel.first][tel.second])
                        continue;
                    vis[tel.first][tel.second] = true;
                    q.push(tel);
                }
            }
        }
        time++;
    }
    return -1;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cout << solve() << "\n";
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
//#include <atcoder/all>
//using namespace atcoder;
#ifndef ONLINE_JUDGE
#define _GLIBCXX_DEBUG
#endif
#define rep(i, n) for (int i = 0; i < (int)(n); ++i)
#define rep2(i, s, n) for (int i = s; i < (int)(n); ++i)
#define Clear(a) a = decltype(a)()
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()
#define vec vector
typedef long long ll;
typedef pair<ll,ll> P;
typedef string::const_iterator state; //構文解析
const double PI=acos(-1);
//const ll big=998244353;
const ll big=1000000007LL;
const ll INF=1e18;
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
ll max(ll x,ll y){
    if(x>y)return x;
    else return y;
}
ll min(ll x,ll y){
    if(x<y)return x;
    else return y;
}
ll expm(ll x,ll y,ll mod=big){
    if(y==0)return 1;//0^0=1
    if(x==1||x==0)return x;
    if(y%2==1)return (expm(x,y-1,mod)*x)%mod;
    ll t=expm(x,y/2,mod);
    return (t*t)%mod;
}
ll exp(ll x,ll y){
    if(y==0)return 1;//0^0=1
    if(x==1||y==0)return x;
    if(y%2==1)return exp(x,y-1)*x;
    ll t=exp(x,y/2);
    return t*t;
}

struct edge{
    ll to,cost;
};

struct graph{
    vector<vector<edge>> g;
    vector<ll> d;

    graph(ll n) : g(n),d(n,INF){}

    void addedge(const ll s,const ll t,const ll cost){
        edge e;
        e.to=t;
        e.cost=cost;
        g[s].emplace_back(e);
    }
    //E+VlogV
    void dijkstra(ll s){//sからstartのdijkstra
        d[s]=0;
        queue<P> q1,q2;
        q1.push(P(0,s));
        while(!q1.empty() || !q2.empty()){
            if(!q1.empty()){
                P pa=q1.front();q1.pop();
                ll k=pa.second;
                if(d[k]<pa.first)continue;
                for(auto e:g[k]){
                    if(d[e.to]>d[k]+e.cost){
                        d[e.to]=d[k]+e.cost;
                        if(e.cost==1)q1.push(P(d[e.to],e.to));
                        else q2.push(P(d[e.to],e.to));
                    }
                }
            }
            else{
                P pa=q2.front();q2.pop();
                ll k=pa.second;
                if(d[k]<pa.first)continue;
                for(auto e:g[k]){
                    if(d[e.to]>d[k]+e.cost){
                        d[e.to]=d[k]+e.cost;
                        if(e.cost==1)q1.push(P(d[e.to],e.to));
                        else q2.push(P(d[e.to],e.to));
                    }
                }
            }
        }
    }
};
int h,w;
int point(int i,int j){
    return i*w+j;
}
pair<int,int> point_back(int k){
    return {k/w , k%w};
}


int main(){
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    cout.precision(10);
    /*--------------------------------*/
    
    cin >> h >> w;
    vector<vector<char>> g(h,vector<char>(w));
    map<char,vector<int>> ma;
    int s,G;
    rep(i,h)rep(j,w){
        cin >> g[i][j];
        if('a'<=g[i][j] && g[i][j] <= 'z'){
            ma[g[i][j]].emplace_back(point(i,j));
        }
        if(g[i][j]=='S'){
            s=point(i,j);
        }if(g[i][j]=='G'){
            G=point(i,j);
        }
    }
    graph gra(h*w+26);
    //全部コストを2倍で計算.
    for(char c='a';c<='z';c++){
        rep(i,ma[c].size()){
            gra.addedge(ma[c][i] , c-'a' + h*w , 1);
            gra.addedge(c-'a' + h*w , ma[c][i],1);
        }
    }
    rep(i,h)rep(j,w){
        rep(k,4){
            int ni=i+dx[k];
            int nj=j+dy[k];
            if(ni<0 || ni>=h || nj<0 || nj>=w || g[ni][nj]=='#')continue;
            gra.addedge(point(i,j),point(ni,nj),2);
        }
    }
    gra.dijkstra(s);
    if(gra.d[G]>=INF)cout << -1 << endl;
    else cout << gra.d[G]/2 << endl;
}