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

#define REP(i,n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define all(x) (x).begin(),(x).end()
using ll = long long;
using P = pair<ll, ll>;
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, -1, 0, 1};
string char_to_string(char val) {
  return string(1, val);
}
int char_to_int(char val) {
  return val - '0';
}
char inverse_char(char c) {
  if(isupper(c)) return tolower(c);
  else return toupper(c);
}
template<class T> inline bool chmin(T& a, T b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template<class T> inline bool chmax(T& a, T b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
struct edge {
  ll to, cost;
};

const int INF = 1001001001;

int main() {
  int H, W; cin >> H >> W;
  vector<string> a(H);
  REP(i, H) cin >> a[i];
  // ワープ使う時、Sから最も近いワープマスからワープするのが最善。
  // BFS中に最初にたどり着いたマスから全部のワープマスへワープするようにすると計算量が落ちる
  vector<vector<int>> dist(H, vector<int>(W, INF));
  queue<P> q;
  REP(i, H) {
    REP(j, W) {
      // Sを探す
      if(a[i][j] == 'S') {
        q.emplace(i, j); //push_backでpairを使ってpushする代わりに、pair型の値をpushしてくれる関数
        dist[i][j] = 0;
      }
    }
  }

  vector<vector<P>> warps(256);
  REP(i, H) {
    REP(j, W) {
      warps[a[i][j]].emplace_back(i, j);
    }
  }

  while(!q.empty()) {
    // 今から見る座標を取得する
    int i = q.front().first; int j = q.front().second;
    // queueから先頭を取り除く
    q.pop();
    // ゴールなら今いる位置の数字を出力する
    if(a[i][j] == 'G') {
      cout << dist[i][j] << endl;
      return 0;
    }
    //上下4方向を探索する
    REP(v, 4) {
      int ni = i + dx[v]; int nj = j + dy[v];
      if(ni < 0 || ni >= H || nj < 0 || nj >= W) continue; // 範囲外ならループをスキップ
      if(a[ni][nj] == '#') continue; // 壁ならループをスキップ
      if(dist[ni][nj] != INF) continue;
      dist[ni][nj] = dist[i][j] + 1;
      q.emplace(ni, nj);
    }

    if(islower(a[i][j])) { // 英字小文字なら...
      for(P p: warps[a[i][j]]) { // warpできる文字の位置を全探索する
        int ni = p.first; int nj = p.second;
        if(dist[ni][nj] != INF) continue;
        dist[ni][nj] = dist[i][j] + 1;
        q.emplace(ni, nj);
      }
      warps[a[i][j]].clear(); // 一度使ったワープ先は空にする
    }
  }
  cout << -1 << endl;
}


//BELIEVE IN YOURSELF
//next_permutation

#include<bits/stdc++.h>
#define ll long long int
#define ld long double
#define pb push_back
#define pob pop_back
#define vi vector<ll>
#define mp make_pair
#define sz size()
#define rep1(i,n) for(ll i=1;i<=n;i++)
#define rep(i,n) for(ll i=0;i<n;i++)
#define fast ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define maxx 100005
#define sec second
#define fi first
#define be begin()
#define en end()
#define sortv(v) sort(v.begin(),v.end());
#define sortr(v) sort(v.rbegin(),v.rend());
#define w() ll _;cin>>_;while(_--)
#define edge pair<ll,ll>
#define pq priority_queue<ll>
#define mod 1000000007
#define Endl "\n"
#define cy cout<<"YES"<<endl;
#define cn cout<<"NO"<<endl;
#define lb(v,x) std::lower_bound(v.begin(),v.end(),x)
#define ub(v,x) std::upper_bound(v.begin(),v.end(),x)

using namespace std;

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

ll n,m;

bool isvalid(ll x,ll y)
{
	if(x>=0 && y>=0 && x<n && y<m)
	{
		return true;
	}
	return false;
}

int main()
{
		fast;

		cin>>n>>m;
		ll i,j;
		string s;
		vector<string>g;
		
		for(i=0;i<n;i++)
		{
			cin>>s;
			g.pb(s);
		}		
		
		ll a[n+1][m+1];
//		ll vis[n+1][m+1];
		
		
		ll inf=1e17;
		ll sx=0,sy=0,ex=0,ey=0;
		
		vector<vector<pair<ll,ll> > >tp(26);
		
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				a[i][j]=inf;
				if(g[i][j]=='S')
				{
					a[i][j]=0;
					sx=i;
					sy=j;
				}
				if(g[i][j]=='G')
				{
					ex=i;
					ey=j;
				}
				if(g[i][j]>='a' && g[i][j]<='z')
				{
					char c=g[i][j];
					tp[c-'a'].pb(mp(i,j));
				}
			}
		}
		
		
		queue<pair<ll,ll> >q;
		
		q.push(mp(sx,sy));
		
		while(!q.empty())
		{
			ll x,y;
			pair<ll,ll>now =q.front();
			q.pop();
			
			x=now.fi;
			y=now.sec;
			
			for(i=0;i<4;i++)
			{
				ll nx,ny;
				pair<ll,ll>next = mp(x+dx[i],y+dy[i]);
				
				nx=next.fi;
				ny=next.sec;
				
				if(isvalid(nx,ny))
				{
					if(g[nx][ny]!='#' && a[nx][ny]==inf)
					{
						a[nx][ny]=a[x][y]+1;
						q.push(mp(nx,ny));
					}
				}
				
				
			}
			
			char c=g[x][y];
			
			if(islower(c))
			{
				for(auto next:tp[c-'a'])
				{
					ll nx,ny;
					nx=next.fi;
					ny=next.sec;
					
					if(a[nx][ny]==inf)
					{
						a[nx][ny]=a[x][y]+1;
						q.push(mp(nx,ny));
					}
				}
			
				tp[c-'a'].clear();
			
			}
		
			
			
		}
		
		ll ans=a[ex][ey];
		
		if(ans==inf)
		{
			cout<<-1<<Endl;
		}
		else
		{
			cout<<ans<<endl;
		}
		
																										
	
	return 0;
}
