#include <bits/stdc++.h>

#define int long long
#define double long double
#define ff first
#define ss second
#define endl '\n'
#define ii pair<int, int>
#define mp make_pair
#define mt make_tuple
#define DESYNC                      \
  ios_base::sync_with_stdio(false); \
  cin.tie(0);                       \
  cout.tie(0)
#define pb push_back
#define vi vector<int>
#define vii vector<ii>
#define all(x) x.begin(), x.end()
#define EPS 1e-9
#define INF 1e18
#define ROOT 1
#define curtime chrono::steady_clock::now().time_since_epoch().count
#define rep(i, beg, n, s) for (int i = beg; i < n; i += s)
using ll = long long;
using namespace std;
const double PI = acos(-1);
const int M = 1000000007;
// const int M = 998244353;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
inline int mod(int n, int m = M) {
  int ret = n % m;
  if (ret < 0) ret += m;
  return ret;
}

int exp(int n, int k, int m = M) {
  if (k == 0) return 1;
  if (k == 1) return n;
  int ax = exp(n, k / 2, m);
  ax = mod(ax * ax, m);
  if (k % 2) ax = mod(ax * n, m);
  return ax;
}

int gcd(int a, int b) {
  if (a == 0)
    return b;
  else
    return gcd(b % a, a);
}

//#define MULTIPLE_TEST_CASE
void solution() {
  int n, m;
  cin >> n >> m;
  vector<vector<char>> A(n, vector<char>(m));
  ii S, G;
  int dst[n][m];
  vector<ii> pos[26];
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      cin >> A[i][j];
      dst[i][j] = INF;
      if (A[i][j] == 'S') S = ii(i, j);
      if (A[i][j] == 'G') G = ii(i, j);
      if (A[i][j] >= 'a' && A[i][j] <= 'z') pos[A[i][j] - 'a'].pb(ii(i, j));
    }
  }

  auto valid = [&](const int x, const int y) {
    return x >= 0 && x <= n - 1 && y >= 0 && y <= m - 1 && A[x][y] != '#';
  };

  set<char> tels;
  for (char c = 'a'; c <= 'z'; c++) {
    tels.insert(c);
  }
  set<tuple<int, int, int>> s;
  dst[S.ff][S.ss] = 0;
  s.insert(mt(0, S.ff, S.ss));
  while (s.size() > 0) {
    int i, j, d;
    tie(d, i, j) = *s.begin();
    s.erase(s.begin());
    if (dst[i][j] != d) continue;

    // take tel
    if (A[i][j] >= 'a' && A[i][j] <= 'z' && tels.count(A[i][j])) {
      tels.erase(A[i][j]);
      for (ii x : pos[A[i][j] - 'a']) {
        if (valid(x.ff, x.ss) && dst[x.ff][x.ss] > d + 1) {
          dst[x.ff][x.ss] = d + 1;
          s.insert(mt(d + 1, x.ff, x.ss));
        }
      }
    }

    // normal
    int dx[] = {-1, 0, 1, 0};
    int dy[] = {0, -1, 0, 1};

    for (int k = 0; k < 4; k++) {
      int ni = i + dx[k];
      int nj = j + dy[k];
      if (valid(ni, nj) && dst[ni][nj] > d + 1) {
        dst[ni][nj] = d + 1;
        s.insert(mt(d + 1, ni, nj));
      }
    }
  }

  if (dst[G.ff][G.ss] >= INF) dst[G.ff][G.ss] = -1;
  cout << dst[G.ff][G.ss] << endl;
}

int32_t main() {
  DESYNC;
  int t = 1;
#ifdef MULTIPLE_TEST_CASE
  cin >> t;
#endif
  while (t--) solution();
}

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template<class T> bool chmin(T& a,T b){if(a>b) {a = b; return true;} return false;}
template<class T> bool chmax(T& a,T b){if(a<b) {a = b; return true;} return false;}
#define rep(i,n) for(int i=0;i<(n);i++)
#define drep(i,n) for(int i=(n)-1;i>=0;i--)
#define all(x) (x).begin(),(x).end()
#define debug(x)  cerr << #x << " = " << (x) << endl;

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int H,W;
    cin >> H >> W;
    auto id = [&](int x,int y){
        return x*W+y;
    };
    auto xy = [&](int a){
        return (pair<int,int>){a/W,a%W};  
    };
    auto in = [&](int x,int y){
        return 0<=x && x<H && 0<=y && y<W;
    };
    vvec<char> S(H,vec<char>(W));
    int sx,sy,gx,gy;
    int M = 26;
    vvec<int> list(M);
    rep(i,H) rep(j,W){
        cin >> S[i][j];
        if(S[i][j]=='S') sx = i,sy = j;
        else if(S[i][j]=='G') gx = i,gy = j;
        else if(isalpha(S[i][j])) list[S[i][j]-'a'].push_back(id(i,j));
    }
    vec<int> dx = {-1,1,0,0},dy = {0,0,-1,1};
    vec<int> dp(H*W+M,-1);
    deque<int> Q;
    dp[id(sx,sy)] = 0;
    Q.push_back(id(sx,sy));
    while(!Q.empty()){
        int now = Q.front(); Q.pop_front();
        if(now<H*W){
            auto [x,y] = xy(now);
            rep(k,4){
                int nx = x+dx[k],ny = y+dy[k];
                if(!in(nx,ny)) continue;
                if(S[nx][ny]=='#') continue;
                if(dp[id(nx,ny)]==-1){
                    dp[id(nx,ny)] = dp[now]+1;
                    Q.push_back(id(nx,ny));
                }
            }
            if(isalpha(S[x][y]) && islower(S[x][y])){
                int to = H*W+(S[x][y]-'a');
                if(dp[to]==-1){
                    dp[to] = dp[now];
                    Q.push_front(to);
                }
            }
        }else{
            for(auto& to:list[now-H*W]){
                if(dp[to]==-1){
                    dp[to] = dp[now]+1;
                    Q.push_back(to);
                }
            }
        }
    }
//    rep(i,H) rep(j,W) cerr << dp[id(i,j)] << (j!=W-1? " ":"\n");
    cout << dp[id(gx,gy)] << "\n";
}