#include <bits/stdc++.h>
using namespace std;
int Convert(string x) {
  int y;
  istringstream DD(x);
  DD >> y;
  return y;
}
struct studentownership {
  map<string, int> TheItemCount;
  multiset<string> MyFinalItems;
  set<pair<string, int> > output;
};
map<string, vector<pair<string, int> > > MyCombinations;
studentownership STOREDATA[101];
int main() {
  int Allies, Basics, Composites, Purchases;
  cin >> Allies >> Basics >> Composites >> Purchases;
  vector<string> MyBasics;
  vector<string> MyComposites;
  vector<string> MyNewNames;
  int q, w, e, r, t;
  for (q = 0; q < Basics; q++) {
    string x;
    cin >> x;
    MyBasics.push_back(x);
  }
  getchar();
  for (q = 0; q < Composites; q++) {
    string x;
    getline(cin, x);
    MyComposites.push_back(x);
  }
  for (q = 0; q < MyComposites.size(); q++) {
    string itemname;
    for (w = 0; true; w++) {
      if (MyComposites[q][w] == ':') {
        itemname = MyComposites[q].substr(0, w);
        MyNewNames.push_back(itemname);
        break;
      }
    }
    w += 2;
    while (true) {
      string subitemname;
      int subitemnumber;
      int start = w;
      for (w; true; w++) {
        if (MyComposites[q][w] == ' ') {
          subitemname = MyComposites[q].substr(start, w - start);
          w++;
          break;
        }
      }
      start = w;
      for (w; true; w++) {
        if (w == MyComposites[q].size() - 1 || MyComposites[q][w + 1] == ',') {
          if (w == MyComposites[q].size() - 1)
            subitemnumber =
                Convert(MyComposites[q].substr(start, w - start + 1));
          else
            subitemnumber =
                Convert(MyComposites[q].substr(start, w - start + 1));
          w += 3;
          break;
        }
      }
      MyCombinations[itemname].push_back(make_pair(subitemname, subitemnumber));
      if (w >= MyComposites[q].size()) break;
    }
  }
  int x;
  string y;
  for (q = 0; q < Purchases; q++) {
    cin >> x >> y;
    STOREDATA[x].TheItemCount[y]++;
    for (w = 0; w < MyNewNames.size(); w++) {
      bool omar = false;
      for (e = 0; e < MyCombinations[MyNewNames[w]].size(); e++) {
        int temp =
            STOREDATA[x].TheItemCount[MyCombinations[MyNewNames[w]][e].first];
        if (temp >= MyCombinations[MyNewNames[w]][e].second) {
          omar = true;
        } else {
          omar = false;
          break;
        }
        if (!omar) break;
      }
      if (omar) {
        STOREDATA[x].MyFinalItems.insert(MyNewNames[w]);
        for (e = 0; e < MyCombinations[MyNewNames[w]].size(); e++) {
          STOREDATA[x].TheItemCount[MyCombinations[MyNewNames[w]][e].first] -=
              MyCombinations[MyNewNames[w]][e].second;
        }
        break;
      }
    }
  }
  for (q = 1; q <= Allies; q++) {
    for (w = 0; w < MyNewNames.size(); w++) {
      int x = STOREDATA[q].MyFinalItems.count(MyNewNames[w]);
      if (x > 0) {
        STOREDATA[q].output.insert(make_pair(MyNewNames[w], x));
      }
    }
    for (w = 0; w < MyBasics.size(); w++) {
      int x = STOREDATA[q].TheItemCount[MyBasics[w]];
      if (x > 0) {
        STOREDATA[q].output.insert(make_pair(MyBasics[w], x));
      }
    }
  }
  for (q = 1; q <= Allies; q++) {
    cout << STOREDATA[q].output.size() << "\n";
    set<pair<string, int> >::iterator IT = STOREDATA[q].output.begin();
    for (IT; IT != STOREDATA[q].output.end(); ++IT) {
      cout << (*IT).first << " " << (*IT).second << "\n";
    }
  }
  return 0;
}
