#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define ti3 tuple<int,int,int>
#define mat vector<vector<int>>
const int inf = 1 << 30;
const ll mod = 1e9 + 7;
const ll linf = 1LL << 62;
const db EPS = 1e-7;
template<class T> void chmin(T& x, T y){if(x > y) x = y;}
template<class T> void chmax(T& x, T y){if(x < y) x = y;}

int N, M;
vector<pii> v;
map<int, vector<int>> mp;
int ok[400010];
vector<int> xs[400010];
int main() {
    cin >> N >> M;
    for (int i = 0; i < M; i++) {
        int X, Y;
        cin >> X >> Y;
        v.push_back({X, Y});
    }
    sort(v.begin(), v.end());
    for (int i = 0; i < M; i++) {
        if (N - M <= v[i].second && v[i].second <= N + M) xs[v[i].second - N + M].push_back(v[i].first); 
    }
    for (int i = 0; i <= 2 * M; i++) {
        xs[i].push_back(2 * N + 1);
    }
    if (xs[M].empty()) {
        ok[M] = 2 * N;
    } else {
        ok[M] = xs[M][0];
    }
    vector<pii> up;
    for (int i = 0; i < M; i++) {
        int y = v[i].second;
        if (N - M <= y && y <= N + M) {
            y -= N - M;
            if (y > 0 && ok[y - 1] >= v[i].first) {
                up.push_back({y, *(upper_bound(xs[y].begin(), xs[y].end(), v[i].first))});
            }
            if (y < 2 * M && ok[y + 1] >= v[i].first) {
                up.push_back({y, *(upper_bound(xs[y].begin(), xs[y].end(), v[i].first))});
            }
        }
        if (i == M - 1 || v[i].first != v[i + 1].first) {
            for (auto u : up) {
                chmax(ok[u.first], u.second);
            }
            up.clear();
        }
    }
    int cnt = 0;
    for (int i = 0; i <= 2 * M; i++) {
        cnt += (ok[i] == 2 * N + 1);
    }
    cout << cnt << endl;
}
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
#define Next(i, u) for (int i = h[u]; i; i = e[i].next)
const int N = 2e3 + 5;
const int M = 3e7 + 5;
const int inf = 1e9;
struct edge { int v, next, w;} e[M];
queue <int> Q;
char s[N][N]; int n, m, S, T, tot, h[N * N], dis[N * N];
int read() {
    char c; int x = 0, f = 1;
    c = getchar();
    while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int c(int x, int y) { return (x - 1) * m + y;}
void add(int u, int v, int w) { e[++tot].v = v, e[tot].w = w, e[tot].next = h[u], h[u] = tot;}
int main () {

    n = read(), m = read();
    rep(i, 1, n) scanf("%s", s[i] + 1);
    rep(i, 1, n) rep(j, 1, m) if(s[i][j] == 'S') S = c(i, j);
    rep(i, 1, n) rep(j, 1, m) if(s[i][j] == 'G') T = c(i, j);
    rep(i, 1, n) rep(j, 1, m) if(s[i][j] != '#') {
        if(s[i - 1][j] != '#' && i > 1) add(c(i, j), c(i - 1, j), 1);
        if(s[i][j - 1] != '#' && j > 1) add(c(i, j), c(i, j - 1), 1);
        if(s[i + 1][j] != '#' && i < n) add(c(i, j), c(i + 1, j), 1);
        if(s[i][j + 1] != '#' && j < m) add(c(i, j), c(i, j + 1), 1);
        if(s[i][j] >= 'a' && s[i][j] <= 'z') add(c(i, j), n * m + s[i][j] - 'a' + 1, 0), add(n * m + s[i][j] - 'a' + 1, c(i, j), 1);
    }
    memset(dis, 0x3f, sizeof(dis));
    dis[S] = 0, Q.push(S);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        Next(i, u) {
            int v = e[i].v; if(dis[v] < inf) continue;
            dis[v] = dis[u] + e[i].w, Q.push(v);
        }
    }
    printf("%d", dis[T] < inf ? dis[T] : -1);
    return 0;
}