#include <cstdio>
#include <iostream>
#include <vector>
#include <list>
#include <cmath>
#include <fstream>
#include <algorithm>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <complex>
#include <iterator>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <stack>
#include <climits>
#include <deque>

using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
double EPS=1e-10;
double EQ(double a,double b){
    return abs(a-b)<EPS;
}
void fast_stream(){
  cin.tie(0);
  std::ios_base::sync_with_stdio(0);
}
template<class T>
string IntToString(T num){
  string res;stringstream ss;ss<<num;
  return ss.str();
}
ll StringToInt(string &str){
  ll res=0;
  for(int i=0;i<(int)str.size();i++)
    res=(res*10+str[i]-'0');
  return res;
}
const int mod=1000000007;
int Na,Nt,Ng,Nc;
int M;
map<string,vector<string> > graph;
map<string,int> dp1;
map<string,int> pat;
string revPat[101];
bool ok;
// patternツ青板つェ200ツづヲツづィツ妥・ツつォツつュツづ按づ?つスツづァfalse
int dfs1(string s){
  if(dp1.count(s)!=0)return dp1[s];
  int res=0;
  if(s[0]=='[')return 1;
  else{
    for(int i=0;i<(int)graph[s].size();i++){
      string ns=graph[s][i];
      res+=dfs1(ns);
      if(res>=200)ok=false;
    }
    return dp1[s]=res;
  }
}
map<string,map<int,int> > dp2;
map<int,int> dfs2(string s){
  if(dp2.count(s)!=0)return dp2[s];
  map<int,int> res;
  if(s[0]=='['){
    string tmp=s.substr(1,s.size()-2);
    sort(tmp.begin(),tmp.end());
    int num=pat[tmp];
    res[num]++;
  }
  else{
    for(int i=0;i<(int)graph[s].size();i++){
      string ns=graph[s][i];
      map<int,int> a=dfs2(ns);
      for(map<int,int>::iterator it=a.begin();it!=a.end();it++)
	res[it->first]+=it->second;
    }
  }
  return dp2[s]=res;
}
int dp[2][51][51][51];
int main(){
  ok=true;
  char chs[]={'A','C','G','T'};
  string start;
  // ATGCツづ継atternツづ永ndexツづつつッ
  for(int mask=0;mask<(1<<4);mask++){
    string s;
    for(int i=0;i<4;i++)
      if((mask>>i)&1)s+=chs[i];
    revPat[mask]=s;
    pat[s]=mask;
  }
  cin>>Na>>Nt>>Ng>>Nc;
  cin>>M;
  string s;
  getline(cin,s);
  for(int i=0;i<M;i++){
    getline(cin,s);
    stringstream ss(s);
    string name;
    ss>>name;name=name.substr(0,name.size()-1);
    if(i==0)start=name;
    while(ss>>s){
      // ツ終ツ端ツ記ツ債?づ?つ?づゥツ湘ェツ債?
      graph[name].push_back(s);
    }
  }
  int b=dfs1(start);
  if(!ok||b!=(Na+Nt+Ng+Nc))cout<<0<<endl;
  else{
    map<int,int> a=dfs2(start);
    // for(map<int,int>::iterator it=a.begin();it!=a.end();it++)
    //   cout<<revPat[it->first]<<" "<<it->second<<endl;
    vector<string> v;
    for(map<int,int>::iterator it=a.begin();it!=a.end();it++)
      for(int i=0;i<it->second;i++)
	v.push_back(revPat[it->first]);
    for(int i=(int)v.size();i>=0;i--){
      int cur=i%2;
      int nxt=(i+1)%2;
      for(int j=0;j<=Nt;j++){
	for(int k=0;k<=Ng;k++){
	  for(int l=0;l<=Nc;l++){
	    ll res=0;
	    if(i==(int)v.size()){
	      if(j==0&&k==0&&l==0)res=1;
	    }
	    else{
	      int m=i+j+k+l-(Nt-Ng-Nc);
	      string &s=v[i];
	      for(int o=0;o<(int)s.size();o++){
		if(s[o]=='A'&&m>0)
		  res=(res+dp[nxt][j][k][l]);
		else if(s[o]=='T'&&j>0)
		  res=(res+dp[nxt][j-1][k][l]);
		else if(s[o]=='G'&&k>0)
		  res=(res+dp[nxt][j][k-1][l]);
		else if(s[o]=='C'&&l>0)
		  res=(res+dp[nxt][j][k][l-1]);
	      }
	    }
	    while(res>=mod)res-=mod;
	    dp[cur][j][k][l]=res;
	  }
	}
      }
    }
    cout<<dp[0][Nt][Ng][Nc]<<endl;
  }
  return 0;
}

Measured memory_bytes: 2344