Problem: In the good old Hachioji railroad station located in the west of Tokyo, there are several parking lines, and lots of freight trains come and go every day.

All freight trains travel at night, so these trains containing various types of cars are settled in your parking lines early in the morning. Then, during the daytime, you must reorganize cars in these trains according to the request of the railroad clients, so that every line contains the “right” train, i.e. the right number of cars of the right types, in the right order.

As shown in Figure 7, all parking lines run in the East-West direction. There are exchange lines connecting them through which you can move cars. An exchange line connects two ends of different parking lines. Note that an end of a parking line can be connected to many ends of other lines. Also note that an exchange line may connect the East-end of a parking line and the West-end of another.

<image>

Cars of the same type are not discriminated between each other. The cars are symmetric, so directions of cars don’t matter either.

You can divide a train at an arbitrary position to make two sub-trains and move one of them through an exchange line connected to the end of its side. Alternatively, you may move a whole train as is without dividing it. Anyway, when a (sub-) train arrives at the destination parking line and the line already has another train in it, they are coupled to form a longer train.

Your superautomatic train organization system can do these without any help of locomotive engines. Due to the limitation of the system, trains cannot stay on exchange lines; when you start moving a (sub-) train, it must arrive at the destination parking line before moving another train.

In what follows, a letter represents a car type and a train is expressed as a sequence of letters. For example in Figure 8, from an initial state having a train "aabbccdee" on line 0 and no trains on other lines, you can make "bbaadeecc" on line 2 with the four moves shown in the figure.

<image>

To cut the cost out, your boss wants to minimize the number of (sub-) train movements. For example, in the case of Figure 8, the number of movements is 4 and this is the minimum.

Given the configurations of the train cars in the morning (arrival state) and evening (departure state), your job is to write a program to find the optimal train reconfiguration plan.



Input

The input consists of one or more datasets. A dataset has the following format:


x y
p1 P1 q1 Q1
p2 P2 q2 Q2
.
.
.
py Py qy Qy
s0
s1
.
.
.
sx-1
t0
t1
.
.
.
tx-1


x is the number of parking lines, which are numbered from 0 to x-1. y is the number of exchange lines. Then y lines of the exchange line data follow, each describing two ends connected by the exchange line; pi and qi are integers between 0 and x - 1 which indicate parking line numbers, and Pi and Qi are either "E" (East) or "W" (West) which indicate the ends of the parking lines.

Then x lines of the arrival (initial) configuration data, s0, ... , sx-1, and x lines of the departure (target) configuration data, t0, ... tx-1, follow. Each of these lines contains one or more lowercase letters "a", "b", ..., "z", which indicate types of cars of the train in the corresponding parking line, in west to east order, or alternatively, a single "-" when the parking line is empty.

You may assume that x does not exceed 4, the total number of cars contained in all the trains does not exceed 10, and every parking line has sufficient length to park all the cars.

You may also assume that each dataset has at least one solution and that the minimum number of moves is between one and six, inclusive.

Two zeros in a line indicate the end of the input.

Output

For each dataset, output the number of moves for an optimal reconfiguration plan, in a separate line.

Example

Input

3 5
0W 1W
0W 2W
0W 2E
0E 1E
1E 2E
aabbccdee
-
-
-
-
bbaadeecc
3 3
0E 1W
1E 2W
2E 0W
aabb
bbcc
aa
bbbb
cc
aaaa
3 4
0E 1W
0E 2E
1E 2W
2E 0W
ababab
-
-
aaabbb
-
-
0 0


Output

4
2
5

Solution (in CPP):

Solution:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>

using namespace std;

template <class Key, class Value>
struct HashMap {

    static const int MAXH = 999983;
    struct Edge {
        Key to;
        Value v;
        Edge *next;
    } *head[MAXH];

    void set(const Key &key, const Value &value) {

        int hv = (unsigned int)key.hash_value() % MAXH;
        Edge *p = new Edge;
        p -> to = key;
        p -> v = value;
        p -> next = head[hv];
        head[hv] = p;
    }

    const Value &get(const Key &key) {

        int hv = (unsigned int)key.hash_value() % MAXH;
        for (Edge *p = head[hv]; p; p = p -> next)
            if (p -> to == key) return p -> v;
    }

    bool exist(const Key &key) {

        int hv = (unsigned int)key.hash_value() % MAXH;
        for (Edge *p = head[hv]; p; p = p -> next)
            if (p -> to == key) return true;
        return false;
    }

    void clear() {

        for (int i = 0; i < MAXH; i++)
        {
            for (Edge *p = head[i], *np; p; p = np)
            {
                np = p -> next;
                delete p;
            }
            head[i] = NULL;
        }
    }
};

const int MAXN = 4;
const int MAXM = MAXN * MAXN * 2;
int n, m, mcnt;
bool trans[MAXN][2][MAXN][2];
//int track[MAXM][2], dir[MAXM][2];

struct State {

    vector<string> s;

    string &operator[](int x) {

        return s[x];
    }

    int hash_value() const {

        unsigned int res = 0, res0;
        for (int i = 0; i < n; i++)
        {
            res0 = 0;
            const string &ref = s[i];
            string::size_type len = ref.length();
            for (int j = 0; j < len; j++)
                res0 = res0 * 131 + ref[j];
            res = res * 13131 + res0;
        }
        return res;
    }

    bool operator==(const State &b) const {

        for (int i = 0; i < n; i++)
            if (s[i] != b.s[i]) return false;
        return true;
    }

    void go(int n0, int d0, int n1, int d1, int k) {

        string out = s[n0].substr(0, k);
        s[n0] = s[n0].erase(0, k);
        if (d0) std::swap(out, s[n0]);
        if (d0 == d1) reverse(out.begin(), out.end());
        if (d1) s[n1] += out;
        else s[n1] = out + s[n1];
    }

    void push_back(const string &b) {

        s.push_back(b);
    }
};

struct Bfs {

    queue<State> q[2], *old, *new_;
    HashMap<State, int> hash;
    int head, tail;
    Bfs *pair;

    void init() {

        hash.clear();
        for (int i = 0; i < 2; i++)
            while (!q[i].empty()) q[i].pop();
        old = q;
        new_ = q + 1;
    }

    int push(const State &ns, int step) {

        if (hash.exist(ns)) return -1;
        if (pair -> hash.exist(ns))
        {
            int t = pair -> hash.get(ns);
            return step + t; 
        }
        hash.set(ns, step);
        new_ -> push(ns);
        return -1;
    }

    int next() {

        while (!old -> empty())
        {
            State &ref = old -> front();
            int nstep = hash.get(ref) + 1;
     //       for (int i = 0; i < mcnt; i++)
            for (int f = 0; f < n; f++)
                for (int t = 0; t < n; t++)
                    for (int fd = 0; fd < 2; fd++)
                        for (int td = 0; td < 2; td++)
                            if (trans[f][fd][t][td])
            {
                string::size_type len = ref[f].length();
                for (int k = 0; k <= len; k++)
                {
                    State v = ref;
                 //   v.go(track[i][0], dir[i][0], track[i][1], dir[i][1], k);
                    v.go(f, fd, t, td, k);
                    int ret = push(v, nstep);
                    if (ret != -1) return ret;
                }
            }
            old -> pop();
        }
        swap(old, new_);
        return -1;
    }
};

Bfs ins[2];

int main() {


    for (;;)
    {
        mcnt = 0;
        scanf("%d %d", &n, &m);
        if (!n && !m) break;
        memset(trans, 0, sizeof trans);
        for (int i = 0; i < m; i++)
        {
            int f, t;
            char fd, td;
            scanf("%d%c %d%c", &f, &fd, &t, &td);
            fd = fd == 'E';
            td = td == 'E';
/*            track[mcnt][0] = f; track[mcnt][1] = t;
            dir[mcnt][0] = fd; dir[mcnt][1] = td;
            mcnt++;

            track[mcnt][0] = t; track[mcnt][1] = f;
            dir[mcnt][0] = td; dir[mcnt][1] = fd;
            mcnt++;
            */
            trans[f][fd][t][td] = true;
            trans[t][td][f][fd] = true;
        }

        State root[2];
        static char buff[20];

        for (int t = 0; t < 2; t++)
        for (int i = 0; i < n; i++)
        {
            scanf("%s", buff);
            root[t].push_back(buff);
            if (root[t][i] == "-") root[t][i] = "";
        }

        for (int i = 0; i < 2; i++) 
        {
            ins[i].init();
            ins[i].pair = ins + !i;
            swap(ins[i].old, ins[i].new_);
            ins[i].push(root[i], 0);
        }
        for (int i = 0; i < 2; i++)
            swap(ins[i].old, ins[i].new_);

        for (int i = 0;; i ^= 1)
        {
            int ret = ins[i].next();
            if (ret != -1) 
            {
                printf("%d\n", ret);
                break;
            }
        }
    }

    return 0;
}