#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define each(i,a) for (auto&& i : a)
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)

const ll linf = 1e18;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    each(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
    rep(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, const vector< vector<T> >& vec) {
    rep(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}
// class AhoCorasick {
//     void clear_graph() {
//         root.child.clear();
//         root.pattern = 0;
//     }
//     void generate_trie(const vector<string>& patterns) {
//         ll n = patterns.size();
//         rep(i, n) {
//             Node* t = &root;
//             each(c, patterns[i]) {
//                 if (t->child.count(c) == 0) {
//                     t->child[c] = Node(nodes.size());
//                     nodes.pb(&t->child[c]);
//                 }
//                 t = &(t->child[c]);
//             }
//             t->pattern++;
//         }
//     }
//     void add_failure_edge() {
//         queue<Node*> Q; Q.push(&root);
//         //幅優先探索で帰納的に失敗時の遷移辺を追加していく
//         while (!Q.empty()) {
//             Node* t = Q.front(); Q.pop();
//             each(p, t->child) {
//                 Q.push(&(p.second));
//                 char c = p.first;
//                 Node* node = &(p.second); // 文字cで遷移する頂点
//                 Node* anode = t->failure; // 失敗したときの遷移先
//                 while ( anode != NULL && anode->child.count(c) == 0 ) {
//                     anode = anode->failure;
//                 }
//                 //遷移失敗時に続けられる別の頂点へ遷移
//                 if (anode == NULL) {
//                     node->failure = &root;
//                 }
//                 else {
//                     node->failure = &(anode->child[c]);
//                 }
//                 //マッチするパターンを追加
//                 node->pattern += node->failure->pattern;
//             }
//         }
//     }
//     //Pattern Match Automatonを構築
//     void make_PMA(const vector<string>& patterns) {
//         clear_graph();
//         generate_trie(patterns);
//         add_failure_edge();
//     }
// public:
//     struct Node {
//         ll id;
//         map<char,Node> child; //遷移辺(!)
//         ll pattern;
//         Node* failure; //遷移失敗時の遷移先ノード
//         Node():failure(NULL), pattern(0) {
//         }
//         Node(ll id):failure(NULL), id(id), pattern(0) {}
//     };
//     vector<Node*> nodes;
//     Node root;
//     AhoCorasick(const vector<string>& patterns) : nodes(0), root(0) {
//         nodes.assign(1, &root);
//         make_PMA(patterns);
//     }
//     pair<Node*, ll> find(Node* node, char c) {
//         ll res = 0;
//         while (node != NULL && node->child.count(c) == 0) {
//             node = node->failure;
//         }
//         if (node == NULL) node = &root;
//         else node = &(node->child[c]);
//         res += node->pattern;
//         return {node, res};
//     }
//     pair<ll, ll> find(ll nid, char c) {
//         auto res = find(nodes[nid], c);
//         return {res.first->id, res.second};
//     }
// };
class AhoCorasick {
    vector<map<char, ll>> G;
    vector<ll> failure, pattern;
    ll fresh_node() {
        const ll res = G.size();
        G.resize(res+1);
        pattern.pb(-1);
        return res;
    }
    ll follow(ll v, char c) const {
        while (v >= 0 && G[v].count(c) == 0) {
            v = failure[v];
        }
        return v < 0 ? 0 : G[v].find(c)->second;
    }
    void generate_trie(const vector<string>& patterns) {
        rep(i, patterns.size()) {
            ll v = 0;
            each(c, patterns[i]) {
                if (G[v].count(c) == 0) {
                    G[v][c] = fresh_node();
                }
                v = G[v][c];
            }
            pattern[v] = i;
        }
    }
    void add_failure_edge() {
        queue<ll> Q; Q.push(0);
        failure.assign(size(), -1);
        while ( !Q.empty() ) {
            ll v = Q.front(); Q.pop();
            each(p, G[v]) {
                char c; ll to; tie(c, to) = p;
                Q.push(p.second);
                failure[to] = follow(failure[v], c);
            }
        }
    }
public:
    AhoCorasick(const vector<string>& patterns) : G(1), pattern(1, -1) {
        generate_trie(patterns);
        add_failure_edge();
    }
    size_t size() const {
        return G.size();
    }
    pair<ll, vector<ll>> find(ll v, char c) const {
        vector<ll> res;
        v = follow(v, c);
        ll now = v;
        while (now >= 0) {
            if (pattern[now] >= 0) res.pb(pattern[now]);
            now = failure[now];
        }
        return {v, res};
    }
};

const ll mod = 1e9+7;
ll mul(ll a, ll b) {
    return a * b % mod;
}
ll mul(initializer_list<ll> t) {
    ll res = 1;
    each(v, t) res = mul(res, v);
    return res;
}
ll add(ll a, ll b) {
    return (a + b) % mod;
}
ll add(initializer_list<ll> t) {
    ll res = 0;
    each(v, t) res = add(res, v);
    return res;
}
ll sub(ll a, ll b) {
    return (a - b + mod) % mod;
}
ll sub(initializer_list<ll> t) {
    auto it = t.begin();
    ll res = *(it++);
    while (it != t.end()) {
        res = sub(res, *(it++));
    }
    return res;
}
ll power(ll x, ll n) {
    ll res = 1;
    for (ll i = 1; i <= n; i <<= 1) {
        if (i & n) res = mul(res, x);
        x = mul(x, x);
    }
    return res;
}
ll inv(ll n) {
    return power(n, mod-2);
}
ll divi(ll a, ll b) {
    return mul(a, inv(b));
}
ll divi(initializer_list<ll> t) {
    auto it = t.begin();
    ll res = *(it++);
    while (it != t.end()) {
        res = divi(res, *(it++));
    }
    return res;
}
vector<ll> fact;
void init_fact(ll n) {
    fact.assign(n+1, 1);
    FOR(i, 1, fact.size()) {
        fact[i] = mul(fact[i-1], i);
    }
}

ll comb(ll n, ll r) {
    if (r < 0) return 0;
    if (r > n) return 0;
    return divi(fact[n], mul(fact[r], fact[n-r]));
}

using Row = vector<ll>;
using Matrix = vector<Row>;
Matrix E(ll n) {
    Matrix res(n, Row(n, 0));
    rep(i, n) res[i][i] = 1;
    return res;
}
Matrix mul(const Matrix& A, const Matrix& B) {
    const ll n = A.size(), m = A[0].size(), l = B[0].size();
    assert(m == B.size());
    Matrix res(n, Row(l, 0));
    rep(i, n) rep(j, m) rep(k, l) {
        res[i][k] = add(res[i][k], mul(A[i][j], B[j][k]));
    }
    return res;
}
Matrix power(Matrix A, ll n) {
    assert(A.size() == A[0].size());
    Matrix res = E(A.size());
    for (ll i = 1; i <= n; i <<= 1) {
        if (i & n) res = mul(res, A);
        A = mul(A, A);
    }
    return res;
}
const ll M = 21;
int dp[M][501][2][600];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    // AhoCorasick aaa({"a", "b", "c", "aa"});
    // cout << aaa.find(aaa.find(0LL, 'a').first, 'a').second << endl;
    // return 0;
    ll n, m, K;
    while (cin >> n >> m >> K, n || m || K) {
        map<string, ll> words;
        vector<vector<ll>> G(1);
        auto get_word_id = [&](const string& word) {
            if (words.count(word) == 0) {
                ll wid = words.size();
                words[word] = wid;
                G.resize(words.size()+1);
            }
            return words[word];
        };
        rep(i, n) {
            string s, t; cin >> s >> t;
            ll a = get_word_id(s);
            ll b = get_word_id(t);
            G[a].pb(b);
        }
        vector<string> rwords(words.size());
        each(p, words) {
            rwords[p.second] = p.first;
            G.back().pb(p.second);
        }
        vector<string> sws(K); cin >> sws;
        AhoCorasick ac(sws);
        const ll V = ac.size();
        fill(dp[0][0][0], dp[M-1][500][2], 0);
        // vector<vector<vector<vector<int>>>> dp(M, vector<vector<vector<int>>>(G.size(), vector<vector<int>>(2, vector<int>(V, 0))));
        dp[0][G.size()-1][0][0] = 1;
        vector<vector<P>> g(V, vector<P>(words.size()));
        rep(i, V) rep(j, words.size()) {
            ll cnt = 0, nid = i;
            each(c, rwords[j]) {
                pair<ll, vector<ll>> result = ac.find(nid, c);
                nid = result.first;
                cnt += result.second.size();
            }
            g[i][j] = {cnt, nid};
        }
        rep(i, m) {
            fill(dp[(i-1+M)%M][0][0], dp[(i-1+M)%M][500][2], 0);
            // dp[(i-1+M)%M].assign(G.size(), vector<vector<int>>(2, vector<int>(V, 0)));
            rep(j, G.size()) rep(k, 2) rep(l, V) {
                if (dp[i%M][j][k][l] == 0) continue;
                each(to, G[j]) {
                    ll cnt, nid; tie(cnt, nid) = g[l][to];
                    if (cnt + k > 1) continue;
                    ll ni = i + rwords[to].size();
                    ll nj = to;
                    ll nk = k + cnt;
                    ll nl = nid;
                    if (ni > m) continue;
                    assert(ni < m+1 && nj < G.size() && nk < 2 && nl < V);
                    // cout << i << " " << j << " " << k << " " << l << endl;
                    // cout << "-> " << ni << " " << nj << " " << nk << " " << nl << endl;
                    dp[ni%M][nj][nk][nl] = add(dp[ni%M][nj][nk][nl], dp[i%M][j][k][l]);
                }
            }
        }
        // cout << dp << endl;
        ll ans = 0;
        rep(i, G.size()) rep(j, V) {
            ans = add(ans, dp[m%M][i][1][j]);
        }
        cout << ans << endl;
    }
}

Measured memory_bytes: 57156