#pragma GCC optimize("O2")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2")
#pragma GCC optimize("Os")

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

#define ff first
#define ss second
#define PI acos(-1)
#define pb push_back
#define ld long double
#define sp fixed<<setprecision
#define bp __builtin_popcountll
#define all(x) x.begin(),x.end()
#define pii pair<long long,long long>
#define FAST ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

const int M = (1e9)+7;
const int N = 1e5+5;
const int INF = 1e9;

signed main()
{
    FAST
    int tc=1;
    //cin>>tc;
    for(int ti=1;ti<=tc;ti++)
    {
        int n,m;
        cin>>n>>m;
        string s[n];
        for(int i=0;i<n;i++)cin>>s[i];
        int dist[n][m], vis[n][m] = {};
        pii st,en;
        vector<pii> x[26];
        int done[26] = {};
        pii dir[4] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1} };
        set<pair<int,pii>> all;
        for(int i=0;i<n;i++)for(int j=0;j<m;j++)
        {
            if(s[i][j] == 'S')st = {i,j};
            if(s[i][j] == 'G')en = {i,j};
            if(s[i][j] >= 'a' && s[i][j] <= 'z')x[s[i][j]-'a'].pb({i,j});
            dist[i][j] = s[i][j] == 'S' ? 0 : INF;
            all.insert({dist[i][j],{i,j}});
        }
        while(true)
        {
            auto it = all.begin();
            pii now = it->ss;
            int d = it->ff;
            if(d == INF)break;
            all.erase(it);
            if(now == en)break;
            vis[now.ff][now.ss] = 1;
            for(int i=0;i<4;i++)
            {
                pii ne = {now.ff+dir[i].ff, now.ss+dir[i].ss};
                if(ne.ff>=0 && ne.ss>=0 && ne.ff<n && ne.ss<m && s[ne.ff][ne.ss] != '#' && !vis[ne.ff][ne.ss] && dist[ne.ff][ne.ss] > d + 1)
                {
                    //all.erase({dist[ne.ff][ne.ss], ne});
                    dist[ne.ff][ne.ss] = d + 1;
                    all.insert({dist[ne.ff][ne.ss], ne});
                }
            }
            if(s[now.ff][now.ss] >= 'a' && s[now.ff][now.ss] <= 'z')
            {
                int ind = s[now.ff][now.ss] - 'a';
                if(done[ind])continue;
                for(pii ne: x[ind])
                {
                    if(!vis[ne.ff][ne.ss] && dist[ne.ff][ne.ss] > d + 1)
                    {
                        //all.erase({dist[ne.ff][ne.ss], ne});
                        dist[ne.ff][ne.ss] = d + 1;
                        all.insert({dist[ne.ff][ne.ss], ne});
                    }
                }
                done[ind] = 1;
            }
        }
        int ans = dist[en.ff][en.ss];
        if(dist[en.ff][en.ss] == INF)ans = -1;
        cout<<ans<<endl;
    }
    return 0;
}

#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
// #include <atcoder/all>
// using namespace atcoder;

// edge[node_from][i] = pair(cost, node_to_i)
vector<long> dijkstra(vector<vector<pair<long, int>>> &edge, int start=0)
{
    priority_queue<pair<long, int>> q;
    int n_node = edge.size();
    vector<long> cost(n_node, -1L);
    q.push(make_pair(0, start));
    while (! q.empty()) {
        auto [now_c, now] = q.top(); q.pop();
        if (cost[now] != -1) continue;
        cost[now] = -now_c;
        for (auto [next_c, next]: edge[now]) {
            if (cost[next] == -1) q.push(make_pair(now_c-next_c, next));
        }
    }
    return cost;
}

void Main()
{
    int h, w;
    cin >> h >> w;
    vector<string> grid(h);
    pair<int, int> start, end;
    vector<vector<pair<int, int>>> potal(256);
    vector<vector<pair<long, int>>> edge(h*w+'z'-'a'+1);
    for (int i = 0; i < h; i++)
    {
        cin >> grid[i];
        for (int j = 0; j < w; j++)
        {
            switch (grid[i][j])
            {
            case 'S':
                start = make_pair(i, j);
                break;
            case 'G':
                end = make_pair(i, j);
                break;
            case '.':
                break;
            case '#':
                break;
            default:
                potal[grid[i][j]].push_back(make_pair(i, j));
                break;
            }
        }
    }
    int d[4][2] = {{-1, 0}, {+1, 0}, {0, -1}, {0, +1}};
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            if (grid[i][j] == '#') continue;
            for (int k = 0; k < 4; k++)
            {
                int dy = d[k][0];
                int dx = d[k][1];
                if (i+dy>=0 && i+dy<h 
                    && j+dx>=0 && j+dx<w 
                    && grid[i+dy][j+dx] != '#') {
                    edge[i*w+j].push_back(make_pair(1, (i+dy)*w+(j+dx)));
                    edge[(i+dy)*w+(j+dx)].push_back(make_pair(1, i*w+j));
                }
            }
        }
    }
    for (int c = 'a'; c <= 'z'; c++)
    {
        for (auto [i, j]: potal[c]) {
            edge[i*w+j].push_back(make_pair(1, w*h+c-'a'));
            edge[w*h+c-'a'].push_back(make_pair(0, i*w+j));
        }
    }

    auto cost = dijkstra(edge, start.first*w+start.second);
    cout << cost[end.first*w+end.second] << endl;
}

int main(int argc, char **argv)
{
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    Main();
    return 0;
}
