#include <array>
#include <cstdlib>
#include <iostream>
#include <map>
#include <queue>
#include <tuple>
#include <unordered_map>
#include <vector>
using namespace std;

constexpr int ALPHA = 26;
constexpr int BASE = 'a';

constexpr int MAX_N = 250;
constexpr int MAX_LEN = 20;
constexpr int MAX_K = 30;
constexpr int MAX_V = MAX_LEN * MAX_K + 1;

constexpr int mod = 1000000007;

struct trie {
	int v;
	int failure;
	array<int, ALPHA> next;
	int match;

	explicit trie(int v_):v(v_), failure(0), match(0) { next.fill(-1); }
};

vector<trie> nodes;

void add(const string &s) {
	int v = 0;

	for(const char &c : s) {
		const int id = c - BASE;
		if(nodes[v].next[id] == -1) {
			nodes[v].next[id] = nodes.size();
			nodes.emplace_back(nodes.size());
		}
		v = nodes[v].next[id];
	}
	nodes[v].match = 1;
}

void construct(const vector<string> &dict) {
	nodes.clear();
	nodes.emplace_back(0);

	for(const auto &s : dict) {
		add(s);
	}

	queue<int> que;
	que.push(0);

	while(!que.empty()) {
		const trie &current = nodes[que.front()];
		que.pop();

		for(int i = 0; i < ALPHA; ++i) {
			const int next_id = current.next[i];

			if(next_id == -1) continue;

			que.push(next_id);

			trie &u = nodes[next_id];

			if(current.v) {
				int f = current.failure;
				while(f && nodes[f].next[i] == -1) {
					f = nodes[f].failure;
				}

				const int nf = nodes[f].next[i];

				if(nf != -1) {
					u.failure = nf;
					u.match += nodes[nf].match;
				}
			}
		}
	}
}

pair<int, int> move_to(int v, const string &s) {
	int match = 0;

	for(const char &c : s) {
		const int id = c - BASE;
		
		while(v && nodes[v].next[id] == -1) {
			v = nodes[v].failure;
		}

		if(v == 0 && nodes[v].next[id] == -1) {
			continue;
		}

		v = nodes[v].next[id];
		match += nodes[v].match;
	}

	return {v, match};
}

unordered_map<string, int> converter(MAX_N);
vector<string> words;
vector<vector<int>> G;

int encode(const string &s) {
	if(!converter.count(s)) {
		converter.insert({s, converter.size()});
		words.emplace_back(s);
		G.emplace_back();
	}
	return converter[s];
}

int main() {
	cin.tie(nullptr);
	ios::sync_with_stdio(false);

	nodes.reserve(MAX_V);
	words.reserve(MAX_N);
	G.reserve(MAX_N * 2);

	for(int n, m, k; cin >> n >> m >> k && n;) {
		converter.clear();
		words.clear();
		G.clear();

		for(int i = 0; i < n; ++i) {
			string from, to;
			cin >> from >> to;
			G[encode(from)].emplace_back(encode(to));
		}

		vector<string> seasonwords(k);
		for(auto &e : seasonwords) cin >> e;
		construct(seasonwords);

		const int num = words.size();

		typedef tuple<int, int, bool> state; // last word, trie v, exist seasonword
		vector<map<state, int>> dp(m + 1);

		for(int i = 0; i < num; ++i) {
			if(static_cast<int>(words[i].size()) > m) continue;

			const auto p = move_to(0, words[i]);
			if(p.second <= 1) dp[words[i].size()][state(i, p.first, p.second)] = 1;
		}

		for(int len = 1; len < m; ++len) {
			for(const auto &curr : dp[len]) {
				int w, v;
				int match;
				tie(w, v, match) = curr.first;

				for(const auto &to : G[w]) {
					const int sum_len = len + words[to].size();
					if(sum_len > m) continue;

					const auto p = move_to(v, words[to]);
					const int sum_match = match + p.second;
					if(sum_match > 1) continue;

					auto &target = dp[sum_len][state(to, p.first, sum_match)];
					target += curr.second;
					if(target >= mod) target -= mod;
				}
			}

			dp[len].clear();
		}

		int ans = 0;
		for(const auto &e : dp[m]) {
			if(get<2>(e.first)) {
				ans += e.second;
				if(ans >= mod) ans -= mod;
			}
		}

		cout << ans << endl;
	}

	return EXIT_SUCCESS;
}

Measured memory_bytes: 4176