#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <cstring>
using namespace std;

struct Trie {
    struct Node {
        int num; // node number
        Node *next[27], *fail;
        int words;

        Node() : words(0) {;}
        Node(int n) : words(0), num(n) {
            for(int i=0; i<27; ++i) next[i] = NULL;
            fail = NULL;
        }
    };

    // default constructor
    Trie() { nodes.clear(); nodes.push_back(new Node(0)); }

    // insert string
    void insert(const string &s) {
        Node *cur = nodes[0];
        for(int i=0; i<s.length(); ++i) {
            if(cur->next[s[i]-'a'] == NULL) {
                cur->next[s[i]-'a'] = new Node(nodes.size());
                nodes.push_back(cur->next[s[i]-'a']);
            }
            cur = cur->next[s[i]-'a'];
        }
        cur->words += 1;
    }

    // list of node
    vector<Node*> nodes;
};

class Aho_Corasick {
public:
    Aho_Corasick(const vector<string> &vs) : keys(vs) {
        _trie = Trie();
        for(int i=0; i<vs.size(); ++i) _trie.insert(vs[i]);
        make_failure_link();
    }

    void make_failure_link() {
        queue<Trie::Node *> q;
        Trie::Node *root = _trie.nodes[0];
        for(int i=0; i<27; ++i) {
            if(root->next[i]) {
                root->next[i]->fail = root;
                q.push(root->next[i]);
            }else root->next[i] = root;
        }

        while(!q.empty()) {
            Trie::Node *t = q.front(); q.pop();
            for(int i=0; i<27; ++i) {
                Trie::Node *u = t->next[i];
                if(u) {
                    q.push(u);
                    Trie::Node *r = t->fail;
                    while(!r->next[i]) r = r->fail;
                    u->fail = r->next[i];
                    u->words += u->fail->words;
                }
            }
        }
    }

    pair<int,int> match(const string &s,int num = 0) {
        Trie::Node *v = _trie.nodes[num];
        int ret = 0;
        for(int i=0; i<s.length(); ++i) {
            while(!v->next[s[i]-'a']) v = v->fail;
            v = v->next[s[i]-'a'];
            if(v->words > 0) ret += v->words;
        }
        return make_pair(ret,v->num);
    }

    void free() {
        for(int i=0; i<_trie.nodes.size(); ++i)
            delete _trie.nodes[i];
    }

    Trie _trie;
    vector<string> keys;
};

const int MAXM = 501;
const int MAXS = 20*30+5;
const int MAXN = 501;
const int mod = 1000000007;
map<int,int> dp[21];
pair<int,int> memo[MAXS][MAXN];

inline int encode(int k,int s,int w) { return (s*MAXN+w)*MAXN+k; }

int main() {
    int n,m,k;
    while(cin>>n>>m>>k, n|m|k) {
        string from,to;

        map<string,int> idx;
        vector<string> ridx;
        vector<pair<int,int> > e;

        for(int i=0; i<n; ++i) {
            cin>>from>>to;

            // make index of word
            if(idx.find(from) == idx.end()) {
                idx[from] = ridx.size();
                ridx.push_back(from);
            }
            if(idx.find(to) == idx.end()) {
                idx[to] = ridx.size();
                ridx.push_back(to);
            }
            e.push_back(make_pair(idx[from],idx[to]));
        }

        vector<vector<int> > edge(idx.size());
        for(int i=0; i<e.size(); ++i) edge[e[i].first].push_back(e[i].second);

        vector<string> kigo(k);
        for(int i=0; i<k; ++i) cin>>kigo[i];
        Aho_Corasick ac(kigo);

        int s = ac._trie.nodes.size();

        for(int i=0; i<s; ++i)
            for(int j=0; j<ridx.size(); ++j)
                memo[i][j] = ac.match(ridx[j],i);

        // hoge
        for(int i=0; i<21; ++i) dp[i].clear();
        for(int i=0; i<ridx.size(); ++i) {
            int m = ridx[i].length();
            pair<int,int> p = ac.match(ridx[i]);
            dp[m%21][encode(p.first,p.second,i)] = 1;
        }

        for(int i=0; i<m; ++i) {
            for(map<int,int>::iterator it = dp[i%21].begin(); it != dp[i%21].end(); ++it) {
                int key = it->first;
                int k = key%MAXN, prev = (key/MAXN)%MAXN, s = (key/MAXN)/MAXN,d = it->second;

                for(int j=0; j<edge[prev].size(); ++j) {
                    int nlen = i+ridx[edge[prev][j]].length();
                    if(nlen > m) continue;

                    pair<int,int> p = memo[s][edge[prev][j]];
                    if(k+p.first < 2) {
                        dp[nlen%21][encode(k+p.first,p.second,edge[prev][j])] += d;
                        dp[nlen%21][encode(k+p.first,p.second,edge[prev][j])] %= mod;
                    }
                }
            }
            if(i < m) dp[i%21].clear();
        }


        ac.free();

        int ans = 0;
        for(int i=0; i<ridx.size(); ++i) {
            for(int j=0; j<MAXS; ++j) {
                ans += dp[m%21][encode(1,j,i)];
                ans %= mod;
            }
        }
        cout<<ans<<endl;
    }
}

Measured memory_bytes: 0