#include <bits/stdc++.h>
using namespace std;
const int AND = 0;
const int OR = 1;
const int NAND = 2;
const int NOR = 3;
const int N = 111;
int n, m, k;
string s;
int a[N][3];
int b[N][3];
vector<int> g[N];
bool st[N];
int ord[N];
int ordSz;
int col[N];
int C;
bool used[N];
bool oldUsed[N];
long long G[N];
int readType() {
  cin >> s;
  if (s == "and") return AND;
  if (s == "or") return OR;
  if (s == "nand") return NAND;
  if (s == "nor") return NOR;
  throw;
}
void read() {
  cin >> n >> m >> k;
  for (int i = 0; i < m; i++) {
    a[i][0] = readType();
    cin >> s;
    int p = 1;
    for (int j = 0; j < n; j++) {
      if (s[j] == 'x') {
        a[i][p++] = j;
      }
    }
  }
  for (int i = 0; i < k; i++) {
    b[i][0] = readType();
    cin >> s;
    int p = 1;
    for (int j = 0; j < m; j++) {
      if (s[j] == 'x') {
        b[i][p++] = j;
      }
    }
  }
}
void addEdge(int v, int u) {
  g[v ^ 1].push_back(u);
  g[u ^ 1].push_back(v);
}
void addGraph(int v, int tp) {
  tp = a[v][0] ^ (tp << 1);
  if (tp == 0) {
    st[2 * a[v][1] + 1] = 1;
    st[2 * a[v][2] + 1] = 1;
  } else if (tp == 1) {
    addEdge(2 * a[v][1] + 1, 2 * a[v][2] + 1);
  } else if (tp == 2) {
    addEdge(2 * a[v][1], 2 * a[v][2]);
  } else if (tp == 3) {
    st[2 * a[v][1]] = 1;
    st[2 * a[v][2]] = 1;
  }
}
void dfsMark(int v) {
  used[v] = 1;
  for (int u : g[v]) {
    if (!used[u]) dfsMark(u);
  }
}
bool checkUsed() {
  for (int i = 0; i < n; i++)
    if (used[2 * i] && used[2 * i + 1]) return false;
  return true;
}
bool checkSAT(long long MASK) {
  for (int i = 0; i < 2 * n; i++) {
    g[i].clear();
    st[i] = 0;
    used[i] = 0;
  }
  for (int i = 0; i < k; i++) {
    if (((MASK >> i) & 1) == 0) continue;
    for (int j = 1; j < 3; j++) addGraph(b[i][j], (int)(b[i][0] < 2));
  }
  for (int i = 0; i < 2 * n; i++)
    if (st[i]) dfsMark(i);
  if (!checkUsed()) return false;
  for (int i = 0; i < n; i++) {
    if (used[2 * i] || used[2 * i + 1]) continue;
    for (int j = 0; j < 2 * n; j++) oldUsed[j] = used[j];
    dfsMark(2 * i);
    if (checkUsed()) continue;
    for (int j = 0; j < 2 * n; j++) used[j] = oldUsed[j];
    dfsMark(2 * i + 1);
    if (!checkUsed()) return false;
  }
  return checkUsed();
}
int intVar[10];
int cntVar;
bool oper(int t, bool v1, bool v2) {
  bool res = 0;
  if (t >= 2) {
    t ^= 2;
    res ^= 1;
  }
  if (t == AND)
    return res ^ (v1 && v2);
  else
    return res ^ (v1 || v2);
}
bool getValConst(int v, int MASK) {
  for (int i = 0; i < cntVar; i++) {
    if (intVar[i] == v) {
      return (MASK >> i) & 1;
    }
  }
  throw;
}
bool getValA1(int v, int MASK) {
  return oper(a[v][0], getValConst(a[v][1], MASK), getValConst(a[v][2], MASK));
}
bool getValA2(int v, int MASK) {
  return oper(a[v][0] ^ 2, getValConst(a[v][1], MASK),
              getValConst(a[v][2], MASK));
}
bool getValB1(int v, int MASK) {
  return oper(b[v][0], getValA1(b[v][1], MASK), getValA1(b[v][2], MASK));
}
bool getValB2(int v, int MASK) {
  return oper(b[v][0] ^ 2, getValA2(b[v][1], MASK), getValA2(b[v][2], MASK));
}
bool solve(int id1, int id2) {
  cntVar = 0;
  for (int i = 1; i < 3; i++)
    for (int j = 1; j < 3; j++) {
      intVar[cntVar++] = a[b[id1][i]][j];
      intVar[cntVar++] = a[b[id2][i]][j];
    }
  sort(intVar, intVar + cntVar);
  cntVar = unique(intVar, intVar + cntVar) - intVar;
  for (int MASK = 0; MASK < (1 << cntVar); MASK++) {
    if (getValB1(id1, MASK) && getValB2(id2, MASK)) return true;
  }
  return false;
}
bool isGoodMask(long long MASK) { return !checkSAT(MASK); }
void eraseFromG(int v, int u) {
  if ((G[v] >> u) & 1) G[v] ^= 1LL << u;
}
int ANS = 0;
void brute(int curAns, long long curMask, long long cand, long long already) {
  if (cand == 0) {
    if (isGoodMask(curMask)) ANS = max(ANS, curAns);
    return;
  }
  bool ok = true;
  for (int i = 0; ok && i < k; i++) {
    if (((already >> i) & 1) == 0) continue;
    if ((G[i] & cand) == cand) ok = false;
  }
  if (!ok) return;
  for (int v = 0; (1LL << v) <= cand; v++) {
    if (((cand >> v) & 1) == 0) continue;
    brute(curAns + 1, curMask | (1LL << v), (cand & G[v]) ^ (1LL << v),
          already & G[v]);
    already |= 1LL << v;
    cand ^= 1LL << v;
  }
}
int main() {
  read();
  for (int i = 0; i < k; i++) G[i] = (1LL << k) - 1;
  for (int i = 0; i < k; i++)
    for (int j = 0; j < k; j++) {
      if (solve(i, j)) {
        eraseFromG(i, j);
        eraseFromG(j, i);
      }
    }
  long long all = 0;
  for (int i = 0; i < k; i++) {
    if (((G[i] >> i) & 1) == 0) continue;
    all |= 1LL << i;
  }
  brute(0, 0, all, 0);
  if (ANS == 0)
    cout << -1 << endl;
  else
    cout << k - ANS << endl;
  return 0;
}
