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

const int var = 4;
const int pmax = 1e4;

int trans(char c) {
	switch (c)
	{
	case 'R': return 0;
	case 'D': return 1;
	case 'L': return 2;
	case 'U': return 3;
	default: assert(false);
	}
}

struct ac_node {
	ac_node *fail;
	ac_node *next[var];
	vector<int> ok;
	ac_node() : fail(nullptr), next{} {}
};

ac_node* get_next(ac_node* p, char c) {
	while (!p->next[trans(c)]) p = p->fail;
	return p->next[trans(c)];
}

class aho_corasick {
	ac_node* new_ac_node() {
		static ac_node pool[pmax];
		static int it = 0;
		assert(it < pmax);
		return &pool[it++];
	}
	vector<int> unite(const vector<int>& a, const vector<int>& b) {
		vector<int> res;
		set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(res));
		return res;
	}
	int K;
	ac_node *root;
public:
	aho_corasick(const vector<string>& Ts) : K(Ts.size()), root(new_ac_node()) {
		ac_node *now;
		root->fail = root;
		for (int i = 0; i < K; i++) {
			auto &T = Ts[i];
			now = root;
			for (auto c : T) {
				if (!now->next[trans(c)]) {
					now->next[trans(c)] = new_ac_node();
				}
				now = now->next[trans(c)];
			}
			now->ok.push_back(i);
		}
		queue<ac_node*> q;
		for (int i = 0; i < var; i++) {
			if (!root->next[i]) {
				root->next[i] = root;
			}
			else {
				root->next[i]->fail = root;
				q.push(root->next[i]);
			}
		}
		while (!q.empty()) {
			now = q.front(); q.pop();
			for (int i = 0; i < var; i++) {
				if (now->next[i]) {
					ac_node *nx = now->fail;
					while (!nx->next[i]) {
						nx = nx->fail;
					}
					now->next[i]->fail = nx->next[i];
					now->next[i]->ok = unite(now->next[i]->ok, nx->next[i]->ok);
					q.push(now->next[i]);
				}
			}
		}
	}
	ac_node* get_root() const {
		return root;
	}
	int get_node_id(ac_node* nd) const {
		return (int)(nd - root);
	}
};

const int INF = 1e8;

const int dx[] = { 1, 0, -1, 0 };
const int dy[] = { 0, 1, 0, -1 };

string D = "DRUL";

using T = tuple<int, int, ac_node*>;

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);
	int n, m, p;
	while (cin >> n >> m, n | m) {
		vector<string> S(n);
		int sx = 0, sy = 0, gx = 0, gy = 0;
		for (int i = 0; i < n; i++) {
			cin >> S[i];
			for (int j = 0; j < (int)S[i].size(); j++) {
				if (S[i][j] == 'S') {
					sx = i;
					sy = j;
				}
				else if (S[i][j] == 'G') {
					gx = i;
					gy = j;
				}
			}
		}
		cin >> p;
		vector<string> pts(p);
		for (int i = 0; i < p; i++) {
			cin >> pts[i];
		}
		aho_corasick aho(pts);
		vector<vector<vector<int>>> f(n, vector<vector<int>>(m, vector<int>(110, INF)));
		queue<T> q;
		q.push(make_tuple(sx, sy, aho.get_root()));
		f[sx][sy][aho.get_node_id(aho.get_root())] = 0;
		while (!q.empty()) {
			auto tup = q.front(); q.pop();
			int x = get<0>(tup), y = get<1>(tup);
			ac_node *nd = get<2>(tup);
			int id = aho.get_node_id(nd);
			for (int i = 0; i < 4; i++) {
				int tx = x + dx[i], ty = y + dy[i];
				ac_node *tnd = get_next(nd, D[i]);
				if (0 <= tx && tx < n && 0 <= ty && ty < m && S[tx][ty] != '#' && tnd->ok.empty() && f[tx][ty][aho.get_node_id(tnd)] == INF) {
					q.push(make_tuple(tx, ty, tnd));
					f[tx][ty][aho.get_node_id(tnd)] = f[x][y][id] + 1;
				}
			}
		}
		int res = INF;
		for (auto val : f[gx][gy]) {
			res = min(res, val);
		}
		cout << (res != INF ? res : -1) << endl;
	}
	return 0;
}



Measured memory_bytes: 4788