#include<iostream>
#include<map>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)

const int mod = 1000000007;
const int TR=27;

struct PMA{
  PMA *next[TR];
  int ac;
  PMA(){fill(next,next+TR,(PMA*)0);ac=0;}
};

const int M = 31;
PMA *buildPMA(string in[],int size,map<PMA*,int> &P){
  PMA *root=new PMA;
  P[root]=0;
  rep(i,size){
    PMA *t = root;
    rep(j,(int)in[i].size()){
      char c=in[i][j]-'a'+1;
      if (t->next[c] == NULL){
	int ind=P.size();
	t->next[c]=new PMA;
	P[t->next[c]]=ind;
      }
      t=t->next[c];
    }
    t->ac++;
  }
  queue<PMA*> Q;
  REP(i,1,TR){
    char c=i;
    if (root->next[c]){
      root->next[c]->next[0]=root;
      Q.push(root->next[c]);
    }else root->next[c]=root;
  }
  
  while(!Q.empty()){
    PMA *t=Q.front();Q.pop();
    //REP(c,'a','z'+1){
    REP(c,1,TR){
      if (t->next[c]){
	Q.push(t->next[c]);	
	PMA *r=t->next[0];
	while(!r->next[c])r=r->next[0];
	t->next[c]->next[0]=r->next[c];
	t->next[c]->ac+=r->next[c]->ac;
      }
    }
  }
  return root;
}

void travarse(PMA *now,char a,PMA* root,map<PMA*,int> &P){
  cout <<"now " << (int)a << " " << now->ac << " "<< P[now] << endl;
  rep(i,TR){
    if (now->next[i] != NULL && 
	now->next[i] != root)travarse(now->next[i],i,root,P);
  }
}

pair<int,int> match(PMA *r,string &tar,map<PMA*,int> &P){
  int ac=0;
  rep(i,(int)tar.size()){
    char c = tar[i]-'a'+1;
    while(!r->next[c])r=r->next[0];
    r=r->next[c];
    ac+=r->ac;
  }
  return make_pair(P[r],ac);
}

const int N = 501;
const int NODE=601;
vector<int> edge[N];
int move[NODE][N];//PMAstate,word -> nextPMA stace
char ac[NODE][N];// PMAstate,wort -> num of ac

void makeGraph(vector<string> &in,map<PMA*,int> &P){
  map<PMA*,int>::iterator itr = P.begin();
  while(itr != P.end()){
    int id=(*itr).second;
    rep(i,in.size()){
      pair<int,int> tmp=match((*itr).first,in[i],P);
      if (tmp.second <= 1){
	move[id][i]=tmp.first;
	ac[id][i]=tmp.second;
      }else move[id][i]=-1,ac[id][i]=-1;
    }
    itr++;
  }
}

/*
const int MOD=21;
int dp[MOD][N][NODE][2];
const int ROOT=0;
int solve(int len,int n,int pmasize,vector<int> &ini,vector<string> &all){
  rep(i,MOD)rep(j,n)rep(k,pmasize)rep(l,2)dp[i][j][k][l]=0;
  //  rep(i,ini.size()){
  //int id=ini[i];
  rep(i,all.size()){
    int id=i;
    int size=all[id].size();
    if (size <= len && move[ROOT][id] != -1){
      dp[size%MOD][id][move[ROOT][id]][ac[ROOT][id]]=1;
    }
  }
  rep(i,len){
    rep(j,n){
      rep(l,pmasize){
	  rep(m,2){
	    if (dp[i%MOD][j][l][m] == 0)continue;
	    rep(k,(int)edge[j].size()){
	      int readword=edge[j][k];
	      int nextlen=i+all[readword].size();
	      int nextn=readword;
	      int nextpma=move[l][readword];
	      int nextac=m+ac[l][readword];
	      if (nextlen > len ||nextpma == -1)continue;
	      if (nextac >= 2)continue;
	      nextlen%=MOD;
	      dp[nextlen][nextn][nextpma][nextac]=
		(dp[nextlen][nextn][nextpma][nextac]+
		 dp[i%MOD][j][l][m])%mod;
	    }
	  }
      }
    }
    rep(j,n)rep(k,pmasize)rep(l,2)dp[i%MOD][j][k][l]=0;
  }
  int ret=0;
  rep(i,n)rep(j,pmasize)ret=(ret+dp[len%MOD][i][j][1])%mod;
  return ret;
}
*/

class st{
public:
  int n,p,ac;
  bool operator<(const st & a)const{
    if (n != a.n)return n < a.n;
    if (p != a.p)return p < a.p;
    return ac < a.ac;
  }
};

const int MOD=21;
map<st,int> dp[MOD];
const int ROOT=0;
int solve(int len,int n,int pmasize,vector<int> &ini,vector<string> &all){
  //rep(i,MOD)rep(j,n)rep(k,pmasize)rep(l,2)dp[i][j][k][l]=0;
  rep(i,MOD)dp[i].clear();
  //  rep(i,ini.size()){
  //int id=ini[i];
  rep(i,all.size()){
    int id=i;
    int size=all[id].size();
    if (size <= len && move[ROOT][id] != -1){
      //dp[size%MOD][id][move[ROOT][id]][ac[ROOT][id]]=1;
      dp[size%mod][(st){id,move[ROOT][id],ac[ROOT][id]}]=1;
    }
  }
  rep(i,len){
    map<st,int>::iterator itr = dp[i%MOD].begin();
    //    rep(j,n){
    while(itr != dp[i%MOD].end()){
      int j=(*itr).first.n,l=(*itr).first.p,m=(*itr).first.ac;
      rep(k,(int)edge[j].size()){
	int readword=edge[j][k];
	int nextlen=i+all[readword].size();
	int nextn=readword;
	int nextpma=move[l][readword];
	int nextac=m+ac[l][readword];
	if (nextlen > len ||nextpma == -1)continue;
	if (nextac >= 2)continue;
	nextlen%=MOD;
	int tmp=dp[nextlen][(st){nextn,nextpma,nextac}];
	dp[nextlen][(st){nextn,nextpma,nextac}]=
	  (tmp+
	   (*itr).second)%mod;
	/*
	dp[nextlen][nextn][nextpma][nextac]=
	  (dp[nextlen][nextn][nextpma][nextac]+
	   dp[i%MOD][j][l][m])%mod;
	*/
      }
      itr++;
    }
    //rep(j,n)rep(k,pmasize)rep(l,2)dp[i%MOD][j][k][l]=0;
    dp[i%MOD].clear();
  }
  int ret=0;
  //rep(i,n)rep(j,pmasize)ret=(ret+dp[len%MOD][i][j][1])%mod;
  map<st,int>::iterator itr = dp[len%MOD].begin();
  while(itr != dp[len%MOD].end()){
    if ((*itr).first.ac == 1)ret=(ret+(*itr).second)%mod;
    itr++;
  }
  return ret;
}


int getindex(string &in,map<string,int> &M,vector<string> &a){
  int index=M.size();
  if (M.find(in) == M.end())M[in]=index,a.push_back(in);
  return M[in];
}

main(){
  int n,len,m;
  static string kigo[M];
  while(cin>>n>>len>>m && n){
    rep(i,N){
      edge[i].clear();
      rep(j,NODE){
	move[j][i]=-1;
	ac[j][i]=-1;
      }
    }
    map<string,int> M;
    map<PMA*,int> P;
    vector<string> all;
    vector<int> ini;
    rep(i,n){
      string f,t;
      cin>>f>>t;
      int tf=getindex(f,M,all),tt=getindex(t,M,all);
      ini.push_back(tf);
      edge[tf].push_back(tt);
    }
    rep(i,m)cin>>kigo[i];

    PMA *root = buildPMA(kigo,m,P);
    makeGraph(all,P);
    sort(ini.begin(),ini.end());ini.erase(unique(ini.begin(),ini.end()),ini.end());
    cout << solve(len,all.size(),P.size(),ini,all) << endl;
    //cout<<"end"<<endl;
  }
  return false;
}

Measured memory_bytes: 2964