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<iostream>
#include<queue>
#include<string>
#include<algorithm>
#include<set>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(C)     (C).begin(),(C).end()
#define WEST 0
#define EAST 1

typedef unsigned long long ull;

class state{
public:
  string data[4];
  ull h[4];
  int cnt;
  state(){
    cnt=0;
    rep(i,4){data[i]="";h[i]=0;}
  }
  bool operator<(const state &a)const{
    rep(i,4)if (h[i] != a.h[i])return h[i] < a.h[i];
    return false;
  }
  bool operator==(const state &a)const{
    rep(i,4)if (h[i] != a.h[i])return false;
    return true;
  }
};

bool edge[4][4][2][2];//from to, from w or e, to w or e

const ull xxx=10007;
ull compute_hash(string &a){
  ull ret=0;
  rep(i,a.size()){
    ret=ret*xxx + a[i];
  }
  return ret;
}

inline void get_all_hash(state &a,int n){
  rep(i,n){
    a.h[i]=compute_hash(a.data[i]);
  }
}

inline void operate(string moveone,string stayone,
		    state &now,int me,int tar,
		    int dir,int tdir){
  if (dir == tdir){
    reverse(moveone.begin(),moveone.end());
  }
  if (tdir == EAST){
    now.data[tar]+=moveone;
  }else if (tdir == WEST){\
    now.data[tar]=moveone+now.data[tar];
  }
  now.data[me]=stayone;
}

void move(int n,state &now,set<state> & S,queue<state> &Q){
  rep(i,n){
    rep(j,now.data[i].size()+1){
      string tmp[2]={now.data[i].substr(0,j),now.data[i].substr(j)};
      rep(k,2){//which tmp[0] or tmp[1]
	rep(l,n){//target line
	  rep(m,2){//west or east
	    if (!edge[i][l][k][m])continue;
	    state next=now;
	    next.cnt++;
	    operate(tmp[k],tmp[1-k],next,i,l,k,m);
	    get_all_hash(next,n);
	    if (S.find(next) == S.end()){
	      S.insert(next);
	      Q.push(next);
	    }
	  }
	}
      }
    }
  }  
}

int bfs(int n,state ini,state goal,set<state> &G,bool fromstart){
  set<state> S;
  queue<state> Q;
  if (fromstart){
    Q.push(ini);
    S.insert(ini);
  }else {
    Q.push(goal);
    G.insert(goal);
  }

  while(!Q.empty()){
    state now = Q.front();
    Q.pop();
    /*
    cout <<"debug "<< fromstart << endl;
    rep(i,n){
      cout << now.data[i] << endl;
    }
    */

    if (fromstart){
      set<state>::iterator itr = G.find(now);
      if (itr != G.end())return now.cnt+(*itr).cnt;
    }else {
      if (now == ini)return now.cnt;
    }

    if (now.cnt ==3)continue;
    if (fromstart)move(n,now,S,Q);
    else move(n,now,G,Q);
  }
  return -1;
}

int solve(int n,state &ini,state &goal){
  set<state> Goal;
  int ans = bfs(n,ini,goal,Goal,false);
  if (ans != -1)return ans;
  ans=bfs(n,ini,goal,Goal,true);
  return ans;
}

int main(){
  int n,m;
  while(cin>>n>>m&&n){
    rep(i,4)rep(j,4)rep(k,2)rep(l,2)edge[i][j][k][l]=false;
    rep(i,m){
      char tfd,ttd;
      int f,t;
      int fd,td;
      cin>>f>>tfd>>t>>ttd;
      if (tfd == 'W')fd=WEST;
      else fd=EAST;
      if (ttd == 'W')td=WEST;
      else td=EAST;
      edge[f][t][fd][td]=true;
      edge[t][f][td][fd]=true;
    }
    state ini,goal;
    rep(i,n){
      cin>>ini.data[i];
      if (ini.data[i] == "-")ini.data[i]="";
    }
    rep(i,n){
      cin>>goal.data[i];
      if (goal.data[i] == "-")goal.data[i]="";
    }
    get_all_hash(ini,n);
    get_all_hash(goal,n);
    
    cout << solve(n,ini,goal) << endl;
  }
}