// 12:17 - 13:14
#include<iostream>
#include<cmath>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cassert>
#include<climits>
#include<map>
#include<queue>
#include<set>
 
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define IINF (INT_MAX)
#define MAX_SP  15
#define MAX_LEN 60
 
using namespace std;
 
typedef pair<int,int> ii;
struct Data{
  int cur,cost;
  ii info;
  Data(int cur=IINF,int cost=IINF,ii info=ii(IINF,IINF)):cur(cur),cost(cost),info(info){}
  bool operator < (const Data& a)const{
    return cost > a.cost;
  }
};
 
int h,w,sp,gp,P;
char G[MAX_LEN][MAX_LEN];
/*
  next_state[index][the number of match]
  0 -> empty
  1 -> spell[0]
  2 -> spell[1]
  ...
 */
ii next_state[MAX_SP][MAX_SP][4];
int mincost[MAX_LEN*MAX_LEN][MAX_SP][MAX_SP];
string spell[MAX_SP];
int  dx[] = {+0,+1,+0,-1};
int  dy[] = {-1,+0,+1,+0};
char dc[] = {'U','R','D','L'};

ii getValue(string s){
  rep(i,P+1){
    int cur = 0;
    rep(j,spell[i].size()){
      if(s[cur] != spell[i][j]){
	break;
      }
      cur++;
      if(cur >= s.size()){
	return ii(i,j+1);
      }
    }
  }
  return ii(0,0);
}

void INIT(){
  rep(i,MAX_SP)rep(j,MAX_SP)rep(k,4)next_state[i][j][k] = ii(0,0);
  
  rep(i,P+1){
    rep(j,spell[i].size()+1){
      rep(dir,4){
	rep(k,j+1){
	  ii value = getValue(spell[i].substr(0,j).substr(k)+dc[dir]);
	  if(value != ii(0,0) && next_state[i][j][dir].second < value.second){
	    next_state[i][j][dir] = value;
	  }
	}
      }
    }
  }
}

inline bool isValid(int x,int y){
  return ( 0 <= x && x < w && 0 <= y && y < h );
}

void compute(){
  
  priority_queue<Data> Q;
  Q.push(Data(sp,0,ii(0,0)));
  rep(i,h*w)rep(j,MAX_SP)rep(k,MAX_SP)mincost[i][j][k] = IINF;
  mincost[sp][0][0] = 0;
  
  while(!Q.empty()){
    
    Data data = Q.top(); Q.pop();
 
    if(data.cur == gp){
      cout << data.cost << endl;
      return;
    }
 
    rep(dir,4){
      
      int nx = data.cur % w + dx[dir];
      int ny = data.cur / w + dy[dir];
      
      if(!isValid(nx,ny))continue;
      
      if(G[ny][nx] == '#')continue;
      
      ii next = next_state[data.info.first][data.info.second][dir];
      
      if(next.first != 0 && spell[next.first].size() == next.second)continue;
      
      if(mincost[nx+ny*w][next.first][next.second] > data.cost + 1){
	mincost[nx+ny*w][next.first][next.second] = data.cost + 1;
	Q.push(Data(nx+ny*w,data.cost+1,next));
      }
    }
  }
  cout << -1 << endl;
}
 
bool cmp(const string& a,const string& b){
  return a.size() < b.size();
}

int main(){
  while(cin >> h >> w,h|w){
    rep(i,h){
      rep(j,w){
	cin >> G[i][j];
	if(G[i][j] == 'S'){
	  sp = j + i * w;
	}
	else if(G[i][j] == 'G'){
	  gp = j + i * w;
	}
      }
    }
    cin >> P;
    spell[0].clear();
    vector<string> tmp;
    rep(i,P){
      cin >> spell[i+1];
      tmp.push_back(spell[i+1]);
    }
    
    sort(tmp.begin(),tmp.end(),cmp);
    
    bool out[tmp.size()];
    rep(i,tmp.size())out[i] = false;
    rep(i,tmp.size()){
      REP(j,i+1,tmp.size()){
	if(tmp[j].find(tmp[i]) != string::npos){
	  out[j] = true;
	}
      }
    }
 
    vector<string> tmp2;
    rep(i,tmp.size())if(!out[i]){
      tmp2.push_back(tmp[i]);
    }
    P = tmp2.size();
    rep(i,P){
      spell[i+1] = tmp2[i];
    }
    
    INIT();
    
    compute();
    
  }
  return 0;
}

Measured memory_bytes: 3544