// 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;
  string debug;
  Data(int cur=IINF,int cost=IINF,ii info=ii(IINF,IINF),string debug="$$$"):cur(cur),cost(cost),info(info),debug(debug){}
  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();
    //cout << "(" << data.cur % w << "," << (int)(data.cur / w) << ") " << data.cost << " info(" << data.info.first << "," << data.info.second << ")" << endl;

    if(data.cur == gp){
      //cout << "path : " << data.debug << endl;
      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,data.debug+dc[dir]));
      }
      
    }
    
  }
  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()){
	bool check = true;
	
	if(tmp[j].find(tmp[i]) == string::npos){
	  check = false;
	}

	if(check){
	  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();
    /*
    rep(i,P+1){
      cout << "spell[" << i<< "] =  " << spell[i] << endl;
      rep(j,spell[i].size()+1){
	rep(dir,4){
	  cout << "next_state[" << i << "][" << j << "][" << dir << "] => " << " | " << spell[i].substr(0,j) << " + " << dc[dir]<< " | " <<" next = (" << next_state[i][j][dir].first << "," << next_state[i][j][dir].second << ")" << endl; 
	}
      }
    }
    */

    compute();

  }
  return 0;
}

Measured memory_bytes: 3912