#include <iostream>
#include <vector>
#include <queue>
#include <utility>
#define rep(i, n) for (long long i = 0; i < (n); ++i)
typedef long long ll;
using namespace std;

int main()
{
    ll H, W;
    ll start_x, start_y, goal_x, goal_y;
    cin >> H >> W;

    vector<vector<char>> map(H, vector<char>(W));
    vector<int> dh = {1, 0, -1, 0};
    vector<int> dw = {0, 1, 0, -1};
    vector<vector<bool>> ready(H, vector<bool>(W, false));
    vector<vector<ll>> answer(H, vector<ll>(W, 0));
    vector<vector<pair<ll, ll>>> warp(30);
    vector<bool> alpha(30, false);
    queue<pair<ll, ll>> Q;

    rep(i, H)
    {
        rep(j, W)
        {
            char input;
            cin >> input;
            if ('a' <= input && 'z' >= input)
            {
                warp[input - 'a'].push_back(make_pair(i, j));
            }
            else if (input == 'S')
            {
                start_y = i;
                start_x = j;
            }
            else if (input == 'G')
            {
                goal_y = i;
                goal_x = j;
            }
            map[i][j] = input;
        }
    }
    Q.push({start_y, start_x});
    ready[start_y][start_x] = true;

    while (!Q.empty())
    {
        ll x, y;
        y = Q.front().first;
        x = Q.front().second;
        Q.pop();
        //ワープ判定
        if (map[y][x] <= 'z' && 'a' <= map[y][x])
        {
            int f = map[y][x] - 'a';
            if (!alpha[f])
            {
                alpha[f] = true;
                rep(i, warp[f].size())
                {
                    auto k = warp[f][i];
                    if (!ready[k.first][k.second])
                    {
                        ready[k.first][k.second] = true;
                        answer[k.first][k.second] = answer[y][x] + 1;
                        Q.push(k);
                    }
                }
            }
        }
        //幅探索
        rep(k, 4)
        {
            int th, tw;
            th = y + dh[k];
            tw = x + dw[k];

            if (th < 0 || th >= H || tw < 0 || tw >= W)
                continue;
            if (map[th][tw] == '#' || ready[th][tw])
                continue;
            ready[th][tw] = true;
            answer[th][tw] = answer[y][x] + 1;
            Q.push({th, tw});
        }
        //debug
        // rep(i, H)
        // {
        //     rep(j, W)
        //     {
        //         cout << answer[i][j] << ',';
        //     }
        //     cout << endl;
        // }
        // cout << endl;
    }
    //debug
    // cout << "answer" << endl;
    // rep(i, H)
    // {
    //     rep(j, W)
    //     {
    //         cout << answer[i][j] << ',';
    //     }
    //     cout << endl;
    // }
    if (answer[goal_y][goal_x] == 0)
    {
        cout << -1 << endl;
    }
    else
    {
        cout << answer[goal_y][goal_x] << endl;
    }

    return 0;
}

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

int main()
{
  int H, W;
  cin >> H >> W;
  vector<vector<int> > road(H*W);
  vector<vector<int> > port(26);
  vector<vector<char> > grid(H, vector<char>(W,'#'));
  int S, G;
  for (int i = 0; i < H; i++)
  {
    for (int j = 0; j < W; j++)
    {
      cin >> grid.at(i).at(j);
      if (grid.at(i).at(j) == 'S')
        S = i*W + j;
      if (grid.at(i).at(j) == 'G')
        G = i*W + j;
      if (grid.at(i).at(j) - 'a' >= 0 && grid.at(i).at(j) - 'a' < 26)
        port.at(grid.at(i).at(j) - 'a').push_back(i*W+j);
    }
  }

  for (int i = 0; i < H; i++)
  {
    for (int j = 0; j < W; j++)
    {
      if (grid.at(i).at(j) == '#') continue;
      if (i != 0 && grid.at(i-1).at(j) != '#') road.at(i*W+j).push_back((i-1)*W+j);
      if (i != H-1 && grid.at(i+1).at(j) != '#') road.at(i*W+j).push_back((i+1)*W+j);
      if (j != 0 && grid.at(i).at(j-1) != '#') road.at(i*W+j).push_back(i*W+j-1);
      if (j != W-1 && grid.at(i).at(j+1) != '#') road.at(i*W+j).push_back(i*W+j+1);
    }
  }
  queue<int> que;
  vector<vector<int> > city(H, vector<int>(W,-1));
  vector<int> port_check(26, 0);
  que.push(S);
  city.at(S/W).at(S%W) = 0;
  int now;
  while(!que.empty())
  {
    now = que.front();
    que.pop();
    for (auto x : road.at(now))
    {
      if (city.at(x/W).at(x%W) >= 0) continue;
      city.at(x/W).at(x%W) = city.at(now/W).at(now%W) + 1;
      que.push(x);
    }
    if (grid.at(now/W).at(now%W) - 'a' >= 0 && grid.at(now/W).at(now%W) - 'a' < 26)
    {
      if (port_check.at(grid.at(now/W).at(now%W) - 'a') == 0)
      {
        for (auto y : port.at(grid.at(now/W).at(now%W) - 'a'))
        {
          if (city.at(y/W).at(y%W) >= 0) continue;
          city.at(y/W).at(y%W) = city.at(now/W).at(now%W) + 1;
          que.push(y);
        }
        port_check.at(grid.at(now/W).at(now%W) - 'a') = 1;
      }
    }
  }
  cout << city.at(G/W).at(G%W) << endl;
}
