#include <vector>
#include <string>
#include <memory>
#include <set>
#include <map>
#include <queue>

#include <iostream>
using namespace std;

#define rep(i,n) for(int i=0,i##_len=n;i<i##_len;i++)
#define all(x) begin(x),end(x)
#define lim(x,r,l) (r<=x&&x<l)
typedef long long ll;
typedef long double ld;

struct PMA {
  bool isRoot = false;
  set<int> matched;
  map<char, PMA*> nexts;
  PMA* faild;
  PMA() : matched() , nexts() , faild() { }
  ~PMA() {
    for(auto&& n : nexts){
      delete n.second;
    }
  }
  static PMA build(const vector<string>& patterns) {
    PMA root;
    root.isRoot = true;
    root.faild = &root;

    for(int i = 0; i < patterns.size(); i++){
      PMA* now = &root;
      for(int j = 0; j < patterns[i].size(); j++){
        if(now->nexts.find(patterns[i][j]) == now->nexts.end()){
          now->nexts[patterns[i][j]] = new PMA;
        }
        now = now->nexts[patterns[i][j]];
      }
      now->matched.insert(i);
    }

    queue<PMA*> que;
    for(auto&& next : root.nexts){
      next.second->faild = &root;
      que.push(next.second);
    }

    while(!que.empty()){
      PMA* now = que.front(); que.pop();
      for(auto&& next : now->nexts){
        char c = next.first;
        PMA* nextfaild = now->faild;
        while(!(nextfaild->isRoot || nextfaild->nexts.find(c) != nextfaild->nexts.end())){
          nextfaild = nextfaild->faild;
        }
        if(nextfaild->nexts.find(c) != nextfaild->nexts.end()){
          now->nexts[c]->faild = nextfaild->nexts[c];
          now->nexts[c]->matched.insert(
            begin(nextfaild->nexts[c]->matched), end(nextfaild->nexts[c]->matched));
        }else{
          now->nexts[c]->faild = &root;
        }

        que.push(now->nexts[c]);
      }
    }
    return root;
  }
  tuple<set<int>, PMA*> match(const string& str, int i = 0, PMA* now_ = nullptr){
    set<int> res;
    PMA* now = now_ ? now_ : this;
    for(; i < str.size(); i++){
      int c = str[i];
      while(!(now->isRoot || now->nexts.find(c) != now->nexts.end())){
        now = now->faild;
      }
      if(now->nexts.find(c) != now->nexts.end()){
        now = now->nexts[c];
      }
      res.insert(begin(now->matched), end(now->matched));
    }
    return make_tuple(res, now);
  }
};


const vector<int> d4x({1, 0, -1, 0});
const vector<int> d4y({0, -1, 0, 1});
const vector<string> d4c({"D", "L", "U", "R"});
int main(){
int n, m;
while(cin >> n >> m, n != 0){
  vector<vector<char>> bd(n, vector<char>(m));
  int sx, sy, gx, gy;
  rep(i, n) { rep(j, m) {
    cin >> bd[i][j];
    if(bd[i][j] == 'S'){ sx = i; sy = j;}
    if(bd[i][j] == 'G'){ gx = i; gy = j;}
  } }

  int p; cin >> p;
  vector<string> patterns(p);
  rep(i, p){
    cin >> patterns[i];
  }

  PMA pma = PMA::build(patterns);

  set<tuple<int, int, PMA*>> visited;
  queue<tuple<int, int, PMA*, int>> que;

  que.emplace(sx, sy, &pma, 0);

  int res = ([&]{
    while(!que.empty()){
      int nx, ny, c; PMA* now;
      tie(nx, ny, now, c) = que.front(); que.pop();
      rep(d, 4){
        int tx = nx + d4x[d], ty = ny+d4y[d];
        tuple<set<int>, PMA*> matched = pma.match(string(d4c[d]), 0, now);
        if(!(tx >= 0 && tx < n && ty >= 0 && ty < m &&
             bd[tx][ty] != '#')){
          continue;
        }
        if(!get<0>(matched).empty()){
          continue;
        }
        tuple<int, int, PMA*> next(tx, ty, get<1>(matched));
        if(visited.find(next) != visited.end()){
          continue;
        }
        visited.insert(next);
        if(tx == gx && ty == gy){
          return c + 1;
        }

        que.emplace(tx, ty, get<1>(matched), c + 1);
      }
    }
  return -1;
  })();

  cout << res << endl;
}
}

Measured memory_bytes: 8952