//
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
const int maxn = 3050;
const int maxm = maxn*maxn*4;
int head[maxm],vis[maxm];
char G[maxn][maxn];
int dis[maxm];
struct Edge{
	int f,t,w,next;
	Edge(int f = 0,int t = 0,int w = 0,int next = 0):f(f),t(t),w(w),next(next){}
}edge[maxm];
int cnt;
const int INF = 1e9;
void addedge(int f,int t,int w){
	edge[cnt] = Edge(f,t,w,head[f]);
	head[f] = cnt++;
}
void dijkstra(int s){
	typedef pair <int,int> node;
	priority_queue<node,vector<node>,greater<node> >q;
	for(int i =1;i< maxm;i++)dis[i] = INF;
	dis[s] = 0;
	q.push(make_pair(dis[s],s));
	while(!q.empty()){
		node tmp = q.top();
		q.pop();
		int u = tmp.second;
		if(vis[u])continue;
		vis[u] = 1;
		for(int i = head[u];~i;i = edge[i].next){
			int v = edge[i].t;
			if(dis[v] > dis[u] + edge[i].w){
				dis[v] = dis[u] + edge[i].w;
				if(!vis[v]){
					q.push(make_pair(dis[v],v));
				}
			}
		}
	}
	return;
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	memset(head,-1,sizeof(head));
	int n,m;
	const int B = 2050*2050+1;
	int S = B+100;
	int T = B+101;
	cin >> n >> m;
	for(int i = 1;i <= n;i++){
		string s;
		cin >> s;
		for(int j = 1;j <= m;j++){
			G[i][j] = s[j-1];
			if(s[j-1] == 'S')S = i*2010+j;
			if(s[j-1] == 'G')T = i*2010+j;
		}
	}
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= m;j++){
			if(G[i][j] != '#'){
				for(int k = -1;k <= 1;k++){
					for(int l = -1;l <= 1;l++)if(abs(k+l) == 1){
						int x = i+k,y = j+l;
						if(x < 1 or x > n or y < 1 or y > m)continue;
						if(G[i][j] != '#')addedge(i*2010+j,x*2010+y,2);
					}
				}
			}
			if(G[i][j] >= 'a' and G[i][j] <= 'z'){
				addedge(i*2010+j,B+G[i][j],1);
				addedge(B+G[i][j],i*2010+j,1);
			}
		}
	}
	dijkstra(S);
	if(dis[T] == INF)cout << -1;
	else cout << dis[T]/2;
	return 0;
}

#include <bits/stdc++.h>
// #include <bits/extc++.h>

using namespace std;
// using namespace __gnu_pbds;

#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=n;i>=a;i--)
#define pii pair<int,int>
#define vi vector<int>
#define vii vector<vi >
#define vpii vector<pii >
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define sz(x) ((int)(x).size())
#define mod(x) (((LL)(x)%MOD+MOD)%MOD)
#define o(X) (1<<(X))
#define oL(X) (1LL<<(X))
#define LL long long
#define ppt(x) ((int)__builtin_popcount(x))
#define mst(x,a) memset(x,a,sizeof(x))

const int INF=0x3f3f3f3f,MOD=1023694381;
const LL INF_LL=0x3f3f3f3f3f3f3f3fLL;

template <typename T>
int getplc(T x,int y) {
	return (int)((x>>y)&1);
}

LL qpow(LL a,LL b=MOD-2,LL _MOD=MOD){
	LL res=1;
	for(;b;b>>=1,a=a*a%_MOD){
		if(b&1)
			res=res*a%_MOD;
	}
	return res;
}

template <typename T>
void ckmin(T &a,T b){ a>b?a=b:0; }
template <typename T>
void ckmax(T &a,T b){ a<b?a=b:0; }

template <typename T>
#define errorl(args...) {  \
	string _s = #args;   \
	replace(_s.begin(), _s.end(), ',', ' ');  \
    stringstream _ss(_s);  \
    istream_iterator<string> _it(_ss);  \
    errl(_it, args);  \
}
void errl(istream_iterator<string> it) {}
template<typename T, typename... Args>	
void errl(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	errl(++it, args...);
}
#define error(args...) {  \
	string _s = #args;  \
	replace(_s.begin(), _s.end(), ',', ' ');  \
	stringstream _ss(_s);  \
	istream_iterator<string> _it(_ss);  \
	err(_it, args);  \
	cerr<<endl; \
}
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << "=" << a << " # ";
	err(++it, args...);
}

int dx4[4]={1,0,-1,0},dy4[4]={0,1,0,-1};
int dx8[8]={1,1,0,-1,-1,-1,0,1},dy8[8]={0,1,1,1,0,-1,-1,-1};
const int N=1e6+5;


char s[2005][2005];
int vis[2005][2005],dis[2005][2005],ins[30];

vector<pair<int,int>> g[30];

void Solve() {
	int n,m,sx,sy,dx,dy;
	cin>>n>>m;
	rep(i,1,n){
		cin>>(s[i]+1);
		rep(j,1,m){
			if(s[i][j]=='S')sx=i,sy=j;
			else if(s[i][j]=='G')dx=i,dy=j;
			else if(islower(s[i][j])){
				g[s[i][j]-'a'].eb(i,j);
			}
		}
	}

	queue<pair<int,int>>que;

	auto push=[&](int x,int y,int stp){
		if(!vis[x][y]){
			vis[x][y]=1;
			dis[x][y]=stp;
			que.push({x,y});
		}
	};

	que.push({sx,sy});
	vis[sx][sy]=1;

	while(!que.empty()){
		auto u=que.front();que.pop();

		if(islower(s[u.fi][u.se])&&!ins[s[u.fi][u.se]-'a']){
			ins[s[u.fi][u.se]-'a']=1;
			for(auto c:g[s[u.fi][u.se]-'a']){
				push(c.fi,c.se,dis[u.fi][u.se]+1);
			}
		}

		rep(i,0,3){
			int tx=dx4[i]+u.fi,ty=dy4[i]+u.se;
			if(tx<1||tx>n||ty<1||ty>m||s[tx][ty]=='#')continue;
			push(tx,ty,dis[u.fi][u.se]+1);
		}
	}

	if(dis[dx][dy]==0)cout<<-1<<'\n';
	else cout<<dis[dx][dy]<<'\n';
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
//    freopen("o1.txt","w",stdout);
#endif
	ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
	Solve();
	return 0;
}