#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <string>
#include <map>
#include <queue>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct AhoCorasick {
  static const int SIZE = 128;
  struct State {
    int index;
    int next[SIZE]; // next[0] is failuer link
    vector<int> accept;
    State(int index) : index(index) {
      memset(next, -1, sizeof(next));
    }
  };

  bool build;
  vector<State> pma;
  vector<int> lens;
  //vector<string. strs;

  AhoCorasick() {
    build = false;
    pma.clear();
    pma.push_back(State(0));
    lens.clear();
    //strs.clear();
  }

  void AddString(const char *str) {
    assert(!build);
    int t = 0;
    for (int i = 0; str[i]; i++) {
      int c = str[i];
      if (pma[t].next[c] == -1) {
        int m = pma.size();
        pma[t].next[c] = m;
        pma.push_back(State(m));
      }
      t = pma[t].next[c];
    }
    pma[t].accept.push_back(lens.size());
    lens.push_back(strlen(str));
    //strs.push_back(str);
  }

  void BuildPMA() {
    assert(!build);
    queue<int> que;  // make failure link using bfs
    for (int c = 1; c < SIZE; c++) {
      if (pma[0].next[c] != -1) {
        pma[pma[0].next[c]].next[0] = 0;
        que.push(pma[0].next[c]);
      } else {
        pma[0].next[c] = 0;
      }
    }
    while (!que.empty()) {
      int t = que.front();
      que.pop();
      for (int c = 1; c < SIZE; c++) {
        if (pma[t].next[c] != -1) {
          que.push(pma[t].next[c]);
          int r = pma[t].next[0];
          while (pma[r].next[c] == -1) {
            r = pma[r].next[0];
          }
          pma[pma[t].next[c]].next[0] = pma[r].next[c];
          for (vector<int>::iterator it = pma[pma[r].next[c]].accept.begin(); it != pma[pma[r].next[c]].accept.end(); it++) {
            pma[pma[t].next[c]].accept.push_back(*it);
          }
        }
      }
    }
    build = true;
  }

  int OneMove(int index, int c) {
    return pma[index].next[c] != -1 ?
      pma[index].next[c] :
      pma[index].next[c] = OneMove(pma[index].next[0], c);
    //while (pma[index].next[c] == -1) { index = pma[index].next[0]; }
    //return pma[index].next[c];
  }

  // return first match indices
  vector<int> Match(const char *t) {
    assert(build);
    int index = 0;
    vector<int> ret(lens.size(), -1);
    int n = strlen(t);
    for (int i = 0; i < n; i++) {
      int c = t[i];
      index = OneMove(index, c);
      for (vector<int>::const_iterator it = pma[index].accept.begin(); it != pma[index].accept.end(); it++) {
        if (ret[*it] != -1) { continue; }
        ret[*it] = i - lens[*it] + 1;
      }
    }
    return ret;
  }
};

typedef vector<vector<int> > Graph;

//=======================================

struct State {
  int prev;
  int index;
  char exist;
  State() {;}
  State(int prev, int index, int exist) : prev(prev), index(index), exist(exist) {;}
  bool operator<(const State &rhs) const {
    //if (depth != rhs.depth) { return depth < rhs.depth; }
    if (prev != rhs.prev) { return prev < rhs.prev; }
    if (index != rhs.index) { return index < rhs.index; }
    return exist < rhs.exist;
  }
};

ll MOD = 1000000007;
int n, m, k, s;
Graph g;
map<string, int> mapto;
string mapfrom[1010];
int len[1010];
AhoCorasick aho;
map<State, int> memo[510];
pair<int, char> moveMemo[1001][1010];

//===========================================

pair<int, int> Move(int index, int word) {
  if (moveMemo[index][word].first != -1) { return moveMemo[index][word]; }
  pair<int, int> ret(index, 0);
  FORIT(it, mapfrom[word]) {
    ret.first = aho.OneMove(ret.first, *it);
    ret.second += aho.pma[ret.first].accept.size();
  }
  ret.second = min(ret.second, 2);
  return moveMemo[index][word] = ret;
}

State NextState(State state, int word) {
  pair<int, char> result = Move(state.index, word);
  return State(word, result.first, state.exist + result.second);
}

char str1[100], str2[100];
int main() {
  while (scanf("%d %d %d", &n, &m, &k), n|m|k) {
    REP(i, 510) { memo[i].clear(); }
    aho = AhoCorasick();
    MEMSET(moveMemo, -1);
    mapto.clear();
    s = 0;
    g = Graph(n * 2);
    REP(i, n) {
      scanf("%s %s", str1, str2);
      if (!mapto.count(str1)) {
        mapto[str1] = s++;
        mapfrom[mapto[str1]] = str1;
        len[mapto[str1]] = strlen(str1);
      }
      if (!mapto.count(str2)) {
        mapto[str2] = s++;
        mapfrom[mapto[str2]] = str2;
        len[mapto[str2]] = strlen(str2);
      }
      g[mapto[str1]].push_back(mapto[str2]);
    }
    REP(i, k) {
      scanf("%s", str1);
      aho.AddString(str1);
    }
    aho.BuildPMA();
    assert(aho.pma.size() <= 1000);
    ll ans = 0;
    REP(i, s) {
      memo[len[i]][NextState(State(-1, 0, 0), i)] += 1;
    }
    REP(i, m + 1) {
      FORIT(it1, memo[i]) {
        State state = it1->first;
        int cnt = it1->second;
        if (i == m) {
          ans = state.exist == 1 ? (ans + cnt) % MOD : ans;
          continue;
        }
        FORIT(it2, g[state.prev]) {
          int ndepth = i + len[*it2];
          if (ndepth > m) { continue; }
          State next = NextState(state, *it2);
          if (next.exist >= 2) { continue; }
          memo[ndepth][next] = (memo[ndepth][next] + cnt) % MOD;
        }
      }
      memo[i].clear();
    }
    printf("%lld\n", ans);
  }
}

Measured memory_bytes: 10000