Problem:
Cyber Guardian
In the good old days, the Internet was free from fears and
terrorism. People did not have to worry about any cyber criminals or mad
computer scientists. Today, however, you are facing atrocious crackers 
wherever you are, unless being disconnected. You have to protect
yourselves against their attacks.
Counting upon your excellent talent for software construction and
strong sense of justice, you are invited to work as a cyber
guardian. Your ultimate mission is to create a perfect firewall system
that can completely shut out any intruders invading networks and protect
children from harmful information exposed on the Net. However, it is
extremely difficult and none have ever achieved it before. As the first 
step, instead, you are now requested to write a software simulator
under much simpler assumptions.
In general, a firewall system works at the entrance of a local network
of an organization (e.g., a company or a university) and enforces its local
administrative policy. It receives both inbound and outbound packets
(note: data transmitted on the Net are divided into small segments
called packets) and carefully inspects them one by one whether or not
each of them is legal. The definition of the legality may
vary from site to site or depend upon the local administrative
policy of an organization. Your simulator should accept data representing
not only received packets but also the local administrative policy.
For simplicity in this problem we assume that each network packet
consists of three fields: its source address, destination address, and
message body. The source address specifies the computer or appliance
that transmits the packet and the destination address specifies the
computer or appliance to which the packet is transmitted. An address
in your simulator is represented as eight digits such as 03214567 or
31415926, instead of using the standard notation of IP addresses
such as 192.168.1.1. Administrative policy is described in
filtering rules, each of which specifies some collection of
source-destination address pairs and defines those packets with the
specified address pairs either legal or illegal.
Input
The input consists of several data sets, each of which represents
filtering rules and received packets in the following format:
n
m
rule
1
rule
2
...
rule
n
packet
1
packet
2
...
packet
m
The first line consists of two non-negative integers
n
and
m
. If both
n
and
m
are zeros, this means the end
of input. Otherwise,
n
lines, each representing a filtering
rule, and
m
lines, each representing an arriving packet, follow
in this order. You may assume that
n
and
m
are less than
or equal to 1,024.
Each
rule
i
is in one of the following formats:
permit
source-pattern
destination-pattern
deny
source-pattern
destination-pattern
A
source-pattern
or
destination-pattern
is a
character string of length eight, where each character is either a
digit ('0' to '9') or a wildcard character '?'. For instance,
"1????5??" matches any address whos
...(truncated)

Submitted solutions:

code_snippet: #include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
const int Max = 1111;
typedef long long LL;
using namespace std;

int n,m,cnt;
char rule[3][Max][111];
char str [3][Max][111];

bool ok(char s1[111],char s2[111])
{
    int len = 8;
    for (int i=0;i<8;++i)
    {
        if ( s2[i]!='?'&& s2[i]!=s1[i] ) return 0;
    }
    return 1;
}

void f()
{
    bool flag = 0;
    for (int i=1;i<=n;++i)
    {
        if (strcmp(rule[0][i],"deny")==0)
        {
            if ( flag ==1 && ok(str[0][cnt],rule[1][i])&&ok(str[1][cnt],rule[2][i]) )
                {
                     flag = 0;
                }
        }
        else{
            if ( flag==0 && ok(str[0][cnt],rule[1][i]) && ok(str[1][cnt],rule[2][i]) )
            {
                flag = 1;
            }
        }
    }
    if (flag) cnt++;
}

int main()
{
 //   freopen("in.txt","r",stdin);
    while (scanf("%d%d",&n,&m) && (n|| m) )
    {
        cnt = 0;
        for (int i=1;i<=n;++i)
        {
          scanf("%s%s%s",rule[0][i],rule[1][i],rule[2][i]);
        }

        for (int i=1;i<=m;++i)
        {
            scanf("%s%s%s",str[0][cnt],str[1][cnt],str[2][cnt]);
            f();
        }

        cout<<cnt<<endl;
        for (int i=0;i<cnt;++i)
        {
            printf("%s %s %s\n",str[0][i],str[1][i],str[2][i]);
        }

    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3756
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define FOR(i,l,r) for(ll i=l;i<r;i++)
#define REP(i,n) FOR(i,0,n)
bool same(string s,string t){
    REP(i,8)if(s[i]!=t[i]&&s[i]!='?'&&t[i]!='?')return false;
    return true;
}
int main(){
    while(1){
        ll N,M;cin>>N>>M;
        if(N+M==0)return 0;
        vector<pair<bool,pair<string,string>>>E(N);
        REP(i,N){
            string s,t,u;cin>>s>>t>>u;
            if(s=="permit")E[i].first=true;
            else E[i].first=false;
            E[i].second=make_pair(t,u);
        }
        reverse(E.begin(),E.end());
        vector<pair<pair<string,string>,string>>ans;
        while(M--){
            string s,t,m;cin>>s>>t>>m;
            REP(i,N){
                if(same(s,E[i].second.first)&&same(t,E[i].second.second)){
                    if(E[i].first)ans.emplace_back(make_pair(make_pair(s,t),m));
                    break;
                }
            }
        }
        cout<<ans.size()<<endl;
        for(auto[p,m]:ans)cout<<p.first<<" "<<p.second<<" "<<m<<endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3360
final_rank: 16

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    while (cin >> n >> m, n+m) {
        vector<string> s(n), t(n);
        vector<bool> f(n);
        for (int i = 0; i < n; i++) {
            string type;
            cin >> type >> s[i] >> t[i];
            f[i] = (type == "permit");
        }
        vector<string> res;
        auto check = [](string &s, string &t) -> bool {
            for (int i = 0; i < min(s.size(), t.size()); i++) {
                if (s[i] == t[i] or s[i] == '?' or t[i] == '?') continue;
                return false;
            }
            return true;
        };
        for (int i = 0; i < m; i++) {
            string a, b, c;
            cin >> a >> b >> c;
            bool ok = false;
            for (int j = 0; j < n; j++) {
                if (check(a, s[j]) and check(b, t[j])) {
                    ok = f[j];
                }
            }
            if (ok) {
                res.push_back(a + " " + b + " " + c);
            }
        }

        cout << res.size() << "\n";
        for (auto r : res) {
            cout << r << "\n";
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3572
final_rank: 17

code_snippet: #include <iostream>
#include <queue>
#include <string.h>
using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001

int N, M;

struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};

struct Data {
  char from[9], to[9], message[51];
};

bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}

void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    cin >> buf >> from >> to;
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strcmp(NOT[i].from, OK[k].from) == 0 &&
          strcmp(NOT[i].to, OK[k].to) == 0) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strcmp(OK[i].from, NOT[k].from) == 0 &&
          strcmp(OK[i].to, NOT[k].to) == 0) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    cin >> data.from >> data.to >> data.message;
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  cout << Q.size() << "\n";
  while (!Q.empty()) {
    cout << Q.front().from << " " << Q.front().to << " " << Q.front().message << "\n";
    Q.pop();
  }
}

int main() {
  while (true) {
    cin >> N >> M;
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3080
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <queue>
#include <cstring>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;

struct Data {
  char from[9], to[9], message[51];
};

struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};

bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}

void func() {
  int ok_index = 0, not_index = 0;
  vector<Info> OK(N), NOT(N);
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    cin >> buf >> from >> to;
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strcmp(NOT[i].from, OK[k].from) == 0 &&
          strcmp(NOT[i].to, OK[k].to) == 0) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strcmp(OK[i].from, NOT[k].from) == 0 &&
          strcmp(OK[i].to, NOT[k].to) == 0) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    cin >> data.from >> data.to >> data.message;
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  cout << Q.size() << "\n";
  while (!Q.empty()) {
    cout << Q.front().from << " " << Q.front().to << " " << Q.front().message << "\n";
    Q.pop();
  }
}

int main() {
  while (true) {
    cin >> N >> M;
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3064
final_rank: 2

code_snippet: #include <algorithm>
#include <cfloat>
#include <cmath>
#include <queue>
#include <stack>
#include <stdio.h>
#include <vector>
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 2836
final_rank: 1

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3288
final_rank: 8

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
inline bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
inline bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
inline void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
inline void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  memset(OK, 0, sizeof(OK));
  memset(NOT, 0, sizeof(NOT));
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) && strCmp(NOT[i].to, OK[k].to)) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) && strCmp(OK[i].to, NOT[k].to)) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) && ambiguousCmp(OK[i].to, data.to)) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) && ambiguousCmp(NOT[i].to, data.to)) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3260
final_rank: 5

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3304
final_rank: 12

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%lu\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3340
final_rank: 14

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3324
final_rank: 13

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3292
final_rank: 9

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3352
final_rank: 15

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3292
final_rank: 9

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3216
final_rank: 4

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void strcpy(char *to, char *str) {
  for (int i = 0; str[i] != '\0'; i++) {
    to[i] = str[i];
    to[i + 1] = '\0';
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3296
final_rank: 11

code_snippet: #include <algorithm>
#include <bits/stdc++.h>

#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001

using namespace std;

typedef long long int ll;
typedef unsigned long long int ull;

int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = strlen(base), length2 = strlen(comp);
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3264
final_rank: 6

code_snippet: #include <algorithm>
#include <bits/stdc++.h>
#include <cfloat>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
int N, M;
struct Info {
  char from[9], to[9];
  int rank;
  bool erased;
};
struct Data {
  char from[9], to[9], message[51];
};
bool strCmp(char *base, char *comp) {
  int length1 = 0, length2 = 0;
  for (int i = 0; base[i] != '\0'; i++)
    length1++;
  for (int i = 0; comp[i] != '\0'; i++)
    length2++;
  if (length1 != length2)
    return false;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i])
      return false;
  }
  return true;
}
bool ambiguousCmp(char *base, char *comp) {
  bool FLG = true;
  for (int i = 0; base[i] != '\0'; i++) {
    if (base[i] != comp[i]) {
      if (base[i] == '?') {
      } else {
        FLG = false;
        break;
      }
    }
  }
  if (FLG)
    return true;
  else {
    return false;
  }
}
void func() {
  int ok_index = 0, not_index = 0;
  Info OK[N], NOT[N];
  for (int i = 0; i < N; i++) {
    OK[i].erased = false;
    NOT[i].erased = false;
  }
  char buf[10], from[9], to[9];
  bool FLG;
  for (int i = 0; i < N; i++) {
    scanf("%s %s %s", buf, from, to);
    if (buf[0] == 'p') {
      strcpy(OK[ok_index].from, from);
      strcpy(OK[ok_index].to, to);
      OK[ok_index].rank = i;
      ok_index++;
    } else {
      strcpy(NOT[not_index].from, from);
      strcpy(NOT[not_index].to, to);
      NOT[not_index].rank = i;
      not_index++;
    }
  }
  for (int i = not_index - 1; i >= 0; i--) {
    for (int k = ok_index - 1; k >= 0; k--) {
      if (NOT[i].rank < OK[k].rank || OK[k].erased == true)
        continue;
      if (strCmp(NOT[i].from, OK[k].from) == true &&
          strCmp(NOT[i].to, OK[k].to) == true) {
        OK[k].erased = true;
        break;
      }
    }
  }
  for (int i = ok_index - 1; i >= 0; i--) {
    for (int k = not_index - 1; k >= 0; k--) {
      if (OK[i].rank < NOT[k].rank || NOT[k].erased == true)
        continue;
      if (strCmp(OK[i].from, NOT[k].from) == true &&
          strCmp(OK[i].to, NOT[k].to) == true) {
        NOT[k].erased = true;
        break;
      }
    }
  }
  queue<Data> Q;
  for (int loop = 0; loop < M; loop++) {
    Data data;
    scanf("%s %s %s", data.from, data.to, data.message);
    FLG = false;
    for (int i = 0; i < ok_index; i++) {
      if (OK[i].erased == true)
        continue;
      if (ambiguousCmp(OK[i].from, data.from) == true &&
          ambiguousCmp(OK[i].to, data.to) == true) {
        FLG = true;
        break;
      }
    }
    if (!FLG)
      continue;
    FLG = true;
    for (int i = 0; i < not_index; i++) {
      if (NOT[i].erased == true)
        continue;
      if (ambiguousCmp(NOT[i].from, data.from) == true &&
          ambiguousCmp(NOT[i].to, data.to) == true) {
        FLG = false;
        break;
      }
    }
    if (FLG) {
      Q.push(data);
    }
  }
  printf("%d\n", Q.size());
  while (!Q.empty()) {
    printf("%s %s %s\n", Q.front().from, Q.front().to, Q.front().message);
    Q.pop();
  }
}
int main() {
  while (true) {
    scanf("%d %d", &N, &M);
    if (N == 0 && M == 0)
      break;
    func();
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3264
final_rank: 6