#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<(b)?(a=b,1):0)
#define chmin(a,b) (a>(b)?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef pair<int,int> pii;
typedef long long ll;

struct Scc {
  vector<vector<int> > G,rG;
  vector<int> vs;
  int V;
  int k;
  vector<bool> used;
  vector<int> cmp;
  void init(int _V) {
    V = _V;
    G.assign(V,vector<int>());
    rG.assign(V,vector<int>());
  }
  void add_edge(int from, int to) {
    G[from].push_back(to);
    rG[to].push_back(from);
  }
  void dfs(int v) {
    used[v] = true;
    FOR(it, G[v]) if (!used[*it]) dfs(*it);
    vs.push_back(v);
  }
  void rdfs(int v) {
    used[v] = true;
    cmp[v] = k;
    FOR(it, rG[v]) if (!used[*it]) rdfs(*it);
  }
  int scc() {
    used.assign(V,0);
    vs.clear();
    REP(v, V) if (!used[v]) dfs(v);
    used.assign(V,0);
    cmp.assign(V,0);
    k = 0;
    for (int i=vs.size()-1; i>=0; --i)
      if (!used[vs[i]]) {
        rdfs(vs[i]);
        k++;
      }
    return k;
  }
  vector<vector<int> > getGraph() {
    vector<vector<int> > res(k);
    map<pii, int> mp;
    REP(i,V) {
      int a = cmp[i];
      FOR(it, G[i]) {
        int b = cmp[*it];
        if (a != b) {
          if (mp[pii(a,b)]++ == 0)
            res[a].push_back(b);
        }
      }
    }
    return res;
  }
};

vector<int> tsort(const vector<vector<int> > &g) {
  int n = g.size();
  vector<int> num(n);
  REP(i, n) FOR(it, g[i]) num[*it]++;
  queue<int> Q;
  REP(i, n) if (num[i] == 0) Q.push(i);
  vector<int> res;
  while(!Q.empty()) {
    int v = Q.front(); Q.pop();
    res.push_back(v);
    FOR(it, g[v]) {
      if (num[*it]) {
        num[*it]--;
        if (num[*it] == 0) Q.push(*it);
      }
    }
  }
  REP(i, n) if (num[i]) return vector<int>();
  return res;
}


int alpha2int(char c) {
  if (isupper(c)) return 26 + c-'A';
  else return c-'a';
}

struct Field {
  int n, m;
  vector<char> cs;
  Scc scc;
  vector<vector<int> > graph;
  vector<ll> gcs;
  vector<int> order;
  vector<int> rorder;
  vector<int> size;
  int N;
  void in() {
    cin >> n >> m;
    cs.clear();
    REP(i,n) {
      char c;
      cin >> c;
      cs.push_back(c);
    }
    scc.init(n);
    REP(i,m) {
      int a, b;
      cin >> a >> b;
      a--;b--;
      scc.add_edge(a,b);
    }
    N = scc.scc();
    graph = scc.getGraph();
    gcs.assign(N,0);
    size.assign(N,0);
    REP(i,n) {
      gcs[scc.cmp[i]] |= 1LL<<alpha2int(cs[i]);
      size[scc.cmp[i]]++;
    }
    order = tsort(graph);
    rorder.assign(N,0);
    REP(i,N) {
      rorder[order[i]] = i;
    }
  }
} aki, maki;

int dp[110][110];

int solve() {
  memset(dp,0,sizeof(dp));
  int A = aki.N;
  int B = maki.N;
  int res = 0;
  REP(i,A+1) {
    REP(j,B+1) {
      if (i<A) {
        FOR(it, aki.graph[aki.order[i]]) {
          int t = aki.rorder[*it];
          chmax(dp[t][j], dp[i][j]); 
        }
      }
      if (j<B) {
        FOR(it, maki.graph[maki.order[j]]) {
          int t = maki.rorder[*it];
          chmax(dp[i][t], dp[i][j]);
        }
      }
      if (i<A && j<B) {
        int hoge = 0;
        if (aki.gcs[aki.order[i]] & maki.gcs[maki.order[j]]) {
          hoge = 1;
          if (aki.size[aki.order[i]] >= 2 &&
              maki.size[maki.order[j]] >= 2) {
            return -1;
          }
        }
        chmax(res, dp[i][j]+hoge);
        FOR(it, aki.graph[aki.order[i]]) {
          FOR(jt, maki.graph[maki.order[j]]) {
            int s = aki.rorder[*it];
            int t = maki.rorder[*jt];
            chmax(dp[s][t], dp[i][j] + hoge);
            if (maki.size[maki.order[j]] >= 2) {
              chmax(dp[s][j], dp[i][j] + hoge);
            }
          }
        }
        if (aki.size[aki.order[i]] >= 2) {
          FOR(jt, maki.graph[maki.order[j]]) {
            int t = maki.rorder[*jt];
            chmax(dp[i][t], dp[i][j] + hoge);
          }
        }
        if (maki.size[maki.order[j]] >= 2) {
          FOR(it, aki.graph[aki.order[i]]) {
            int s = aki.rorder[*it];
            chmax(dp[s][j], dp[i][j] + hoge);
          }
        }        
      }
    }
  }
  return res;
}

int main() {
  aki.in();
  maki.in();
  cout << solve() << endl;
}

Measured memory_bytes: 1536