#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,n) for(ll i=0;i<(n);i++)
const ll INF = 1LL<<60;

int main(){
  ll diri[4]={0,1,0,-1};
  ll dirj[4]={1,0,-1,0};

  
  ll H,W;
  cin>>H>>W;
  char a[H][W];
  pair<ll,ll> goal;
  queue<pair<ll,ll>> que;
  vector<vector<ll>> dist(H,vector<ll>(W,-1));
  vector<vector<pair<ll,ll>>> warp(26,vector<pair<ll,ll>>(0,make_pair(0,0)));
rep(i,H){
  rep(j,W){
    cin>>a[i][j];
    if(a[i][j]=='S'){que.push(make_pair(i,j));dist[i][j]=0;}
    if(a[i][j]=='G'){goal=make_pair(i,j);}
    if(0<=a[i][j]-'a'&&a[i][j]-'a'<26){warp[a[i][j]-'a'].push_back(make_pair(i,j));}
  }
}
  
 // ll ans=0;
  vector<ll> distwarp(26,-1);
  while(!que.empty()){
    if(dist[goal.first][goal.second]>0)break;
    ll ni=que.front().first;
    ll nj=que.front().second;
    que.pop();
    rep(i,4){
      if(diri[i]+ni<0||diri[i]+ni>=H||dirj[i]+nj<0||dirj[i]+nj>=W)continue;
	  if(a[diri[i]+ni][dirj[i]+nj]=='#')continue;
      if(dist[diri[i]+ni][dirj[i]+nj]<0){
        dist[diri[i]+ni][dirj[i]+nj]=dist[ni][nj]+1;
        que.push(make_pair(diri[i]+ni,dirj[i]+nj));
      }
    }

    if(0<=a[ni][nj]-'a'&&a[ni][nj]-'a'<26){
      if(distwarp[a[ni][nj]-'a']==0)continue;
      distwarp[a[ni][nj]-'a']=0;
      rep(i,(ll)warp[a[ni][nj]-'a'].size()){
        ll warpi=warp[a[ni][nj]-'a'][i].first;
        ll warpj=warp[a[ni][nj]-'a'][i].second;
        if(dist[warpi][warpj]<0){
        dist[warpi][warpj]=dist[ni][nj]+1;
        que.push(make_pair(warpi,warpj));
        } 
      }
    }
  }

  
  
  ll ans=dist[goal.first][goal.second];
  cout<<ans<<endl;
}

//debug icin gdb kullanmayi dene
#include<bits/stdc++.h>
using namespace std;
#define mods 1000000007
#define pb push_back
#define mp make_pair
#define st first
#define nd second
typedef long long int lint;
typedef unsigned long long int ulint;
lint fastpow(lint tab,lint us){
	if(tab==0) return 0;
	if(tab==1) return 1;
	if(us==0) return 1;
	if(us==1) return tab%mods;
	tab%=mods;
	if(us%2==1) return tab*fastpow(tab,us-1)%mods;
	lint a=fastpow(tab,us/2)%mods;
	return a*a%mods;
}
lint h,w,t=1;
char mat[2020][2020];
bool visited[2020][2020],visited2[35];
vector<pair<lint,lint> > dizi[35];
pair<lint,lint> s,g;
void solve(){
	lint i,j,k;
	char a;
	for(i=0;i<2020;i++) for(j=0;j<2020;j++) mat[i][j]='#';
	cin>>h>>w;
	for(i=1;i<=h;i++){
		for(j=1;j<=w;j++){
			cin>>a;
			mat[i][j]=a;
			if(a=='S') s=mp(i,j);
			else if(a=='G') g=mp(i,j);
			else if(a>='a' and a<='z') dizi[a-'a'].pb(mp(i,j));
		}
	}
	queue<pair<lint,pair<lint,lint> > > sira;
	if(mat[s.st][s.nd+1]!='#') sira.push(mp(1,mp(s.st,s.nd+1)));
	if(mat[s.st][s.nd-1]!='#') sira.push(mp(1,mp(s.st,s.nd-1)));
	if(mat[s.st+1][s.nd]!='#') sira.push(mp(1,mp(s.st+1,s.nd)));
	if(mat[s.st-1][s.nd]!='#') sira.push(mp(1,mp(s.st-1,s.nd)));
	visited[s.st][s.nd]=1;
	while(!sira.empty()){
		pair<lint,pair<lint,lint> > te=sira.front();
		sira.pop();
		lint x=te.nd.st,y=te.nd.nd;
		if(visited[x][y])continue;
		visited[x][y]=1;
		if(mat[x][y]=='G'){cout<<te.st<<endl; return;}
		if(mat[x][y]>='a' and mat[x][y]<='z' and visited2[mat[x][y]-'a']==0){
			for(i=0;i<dizi[mat[x][y]-'a'].size();i++){
				if(dizi[mat[x][y]-'a'][i].st!=x or dizi[mat[x][y]-'a'][i].nd!=y){
					sira.push(mp(te.st+1,mp(dizi[mat[x][y]-'a'][i].st,dizi[mat[x][y]-'a'][i].nd)));
				}
			}
			visited2[mat[x][y]-'a']=1;
		}
		if(!visited[x][y+1] and mat[x][y+1]!='#') sira.push(mp(te.st+1,mp(x,y+1)));
		if(!visited[x][y-1] and mat[x][y-1]!='#') sira.push(mp(te.st+1,mp(x,y-1)));
		if(!visited[x+1][y] and mat[x+1][y]!='#') sira.push(mp(te.st+1,mp(x+1,y)));
		if(!visited[x-1][y] and mat[x-1][y]!='#') sira.push(mp(te.st+1,mp(x-1,y)));
	}
	cout<<-1<<endl;


	return;
}

int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
//	cin>>t;
	while(t--) solve();
	return 0;
}

