#include <bits/stdc++.h>
using namespace std;
struct tarjan_t {
  int n;
  vector<vector<int>> adj;
  vector<int> preorder, inv_preorder, highest_reach;
  stack<int> active;
  vector<bool> is_active;
  vector<vector<int>> cnts;
  vector<int> cnt_of;
  tarjan_t(int _n)
      : n(_n),
        adj(n),
        inv_preorder(n, -1),
        highest_reach(n, n),
        is_active(n, false),
        cnt_of(n, -1) {}
  void dfs(int v) {
    inv_preorder[v] = preorder.size();
    preorder.push_back(v);
    highest_reach[v] = inv_preorder[v];
    active.push(v);
    is_active[v] = true;
    for (int u : adj[v]) {
      if (inv_preorder[u] == -1) {
        dfs(u);
        highest_reach[v] = min(highest_reach[v], highest_reach[u]);
      } else if (is_active[u]) {
        highest_reach[v] = min(highest_reach[v], inv_preorder[u]);
      }
    }
    if (highest_reach[v] == inv_preorder[v]) {
      vector<int> cnt;
      int u;
      do {
        u = active.top();
        active.pop();
        is_active[u] = false;
        cnt.push_back(u);
        cnt_of[u] = cnts.size();
      } while (u != v);
      cnts.push_back(move(cnt));
    }
  }
  void solve() {
    for (int v = 0; v < n; ++v)
      if (inv_preorder[v] == -1) dfs(v);
  }
};
struct twosat_t {
  int n;
  vector<vector<int>> adj;
  twosat_t() {}
  twosat_t(int _n) : n(_n), adj(2 * n) {}
  void add_implication(int a, int b) { adj[a].push_back(b); }
  bool solve() {
    tarjan_t tarjan(2 * n);
    tarjan.adj = adj;
    tarjan.solve();
    for (int i = 0; i < n; ++i)
      if (tarjan.cnt_of[2 * i] == tarjan.cnt_of[2 * i + 1]) return false;
    return true;
  }
};
enum gate_t {
  AND,
  OR,
  NAND,
  NOR,
};
gate_t mirror(gate_t g) {
  if (g == AND) return OR;
  if (g == OR) return AND;
  if (g == NAND) return NOR;
  if (g == NOR) return NAND;
  assert(false);
  return (gate_t)-1;
}
int apply_gate(gate_t g, int a, int b) {
  if (g == AND) return a & b;
  if (g == OR) return a | b;
  if (g == NAND) return !(a & b);
  if (g == NOR) return !(a | b);
  assert(false);
  return -1;
}
const char *gate_to_string(gate_t g) {
  if (g == AND) return "and";
  if (g == OR) return "or";
  if (g == NAND) return "nand";
  if (g == NOR) return "nor";
  return "";
}
struct expr_t {
  int input_id = -1;
  gate_t gate;
  expr_t *sub0 = nullptr, *sub1 = nullptr;
  int enforce_value = -1;
  expr_t() {}
  expr_t(int _id) : input_id(_id) {}
  expr_t(gate_t _gate, expr_t *_sub0, expr_t *_sub1)
      : gate(_gate), sub0(_sub0), sub1(_sub1) {}
  int compute_normal() {
    if (enforce_value != -1) return enforce_value;
    assert(input_id == -1);
    return apply_gate(gate, sub0->compute_normal(), sub1->compute_normal());
  }
  int compute_changed() {
    if (enforce_value != -1) return enforce_value;
    assert(input_id == -1);
    return apply_gate(mirror(gate), sub0->compute_normal(),
                      sub1->compute_normal());
  }
  void add_constraints(int target_value, twosat_t &twosat) {
    assert(sub0->input_id >= 0);
    assert(sub1->input_id >= 0);
    bool v0_implies_v1[2][2] = {{true, true}, {true, true}};
    bool v1_implies_v0[2][2] = {{true, true}, {true, true}};
    for (int v0 = 0; v0 < 2; ++v0)
      for (int v1 = 0; v1 < 2; ++v1) {
        int res = apply_gate(gate, v0, v1);
        if (res == target_value) {
          v0_implies_v1[v0][v1 ^ 1] = false;
          v1_implies_v0[v1][v0 ^ 1] = false;
        }
      }
    for (int v0 = 0; v0 < 2; ++v0)
      for (int v1 = 0; v1 < 2; ++v1)
        if (v0_implies_v1[v0][v1]) {
          twosat.add_implication(sub0->input_id * 2 + v0,
                                 sub1->input_id * 2 + v1);
        }
    for (int v1 = 0; v1 < 2; ++v1)
      for (int v0 = 0; v0 < 2; ++v0)
        if (v1_implies_v0[v1][v0]) {
          twosat.add_implication(sub1->input_id * 2 + v1,
                                 sub0->input_id * 2 + v0);
        }
  }
};
string read_string() {
  char *str;
  scanf("%ms", &str);
  string result(str);
  free(str);
  return result;
}
vector<int> read_gate_ids() {
  string s = read_string();
  vector<int> result;
  for (int i = 0; i < (int)s.size(); ++i)
    if (s[i] == 'x') result.push_back(i);
  assert((int)result.size() == 2);
  return result;
}
gate_t gate_from_str(const string &s) {
  if (s == "and") return AND;
  if (s == "nand") return NAND;
  if (s == "or") return OR;
  if (s == "nor") return NOR;
  assert(false);
  return (gate_t)-1;
}
void add_inputs(expr_t *expr, vector<int> &output) {
  if (expr->input_id >= 0) output.push_back(expr->input_id);
  if (expr->sub0) add_inputs(expr->sub0, output);
  if (expr->sub1) add_inputs(expr->sub1, output);
}
vector<int> get_inputs(vector<expr_t *> exprs) {
  vector<int> result;
  for (expr_t *expr : exprs) add_inputs(expr, result);
  sort(result.begin(), result.end());
  result.resize(unique(result.begin(), result.end()) - result.begin());
  return result;
}
void dfs(int v, int side, vector<bool> &mark, vector<vector<int>> &adj,
         vector<int> &side0, vector<int> &side1) {
  mark[v] = true;
  if (side == 0)
    side0.push_back(v);
  else
    side1.push_back(v);
  for (int u : adj[v])
    if (!mark[u]) dfs(u, side ^ 1, mark, adj, side0, side1);
}
int main() {
  int ni, nl1, nl2;
  scanf("%d %d %d", &ni, &nl1, &nl2);
  vector<expr_t> input_exprs(ni);
  for (int i = 0; i < ni; ++i) {
    input_exprs[i] = expr_t(i);
  }
  vector<expr_t> l1exprs(nl1);
  for (int i = 0; i < nl1; ++i) {
    string gate_str = read_string();
    vector<int> ids = read_gate_ids();
    l1exprs[i] = expr_t(gate_from_str(gate_str), &input_exprs[ids[0]],
                        &input_exprs[ids[1]]);
  }
  vector<expr_t> l2exprs(nl2);
  for (int i = 0; i < nl2; ++i) {
    string gate_str = read_string();
    vector<int> ids = read_gate_ids();
    l2exprs[i] =
        expr_t(gate_from_str(gate_str), &l1exprs[ids[0]], &l1exprs[ids[1]]);
  }
  int nalways_use = 0;
  vector<expr_t> new_l2exprs;
  for (int i = 0; i < nl2; ++i) {
    vector<int> input_ids = get_inputs({&l2exprs[i]});
    bool never_use = false, always_use = true;
    for (int s = 0; s < (1 << input_ids.size()); ++s) {
      for (int j = 0; j < (int)input_ids.size(); ++j) {
        input_exprs[input_ids[j]].enforce_value = ((s & (1 << j)) != 0);
      }
      int res_normal = l2exprs[i].compute_normal();
      int res_changed = l2exprs[i].compute_changed();
      if (res_normal && res_changed) never_use = true;
      if (res_normal || res_changed) always_use = false;
    }
    for (int j = 0; j < (int)input_ids.size(); ++j)
      input_exprs[input_ids[j]].enforce_value = -1;
    assert(!(always_use && never_use));
    if (never_use) {
    } else if (always_use) {
      ++nalways_use;
    } else {
      new_l2exprs.push_back(l2exprs[i]);
    }
  }
  l2exprs = new_l2exprs;
  int orig_nl2 = nl2;
  nl2 = l2exprs.size();
  vector<vector<int>> adj(nl2);
  for (int i = 0; i < nl2; ++i)
    for (int j = i + 1; j < nl2; ++j) {
      vector<int> input_ids = get_inputs({&l2exprs[i], &l2exprs[j]});
      bool conflict = false;
      for (int s = 0; s < (1 << input_ids.size()); ++s) {
        for (int k = 0; k < (int)input_ids.size(); ++k) {
          input_exprs[input_ids[k]].enforce_value = ((s & (1 << k)) != 0);
        }
        int res_normal =
            l2exprs[i].compute_normal() || l2exprs[j].compute_normal();
        int res_changed =
            l2exprs[i].compute_changed() || l2exprs[j].compute_changed();
        if (res_normal && res_changed) {
          conflict = true;
          break;
        }
      }
      for (int k = 0; k < (int)input_ids.size(); ++k) {
        input_exprs[input_ids[k]].enforce_value = -1;
      }
      if (conflict) {
        adj[i].push_back(j);
        adj[j].push_back(i);
      }
    }
  vector<bool> mark(nl2, false);
  vector<int> left_side, right_side;
  for (int i = 0; i < nl2; ++i)
    if (!mark[i]) {
      vector<int> side0, side1;
      dfs(i, 0, mark, adj, side0, side1);
      if (side0.size() > side1.size()) swap(side0, side1);
      left_side.insert(left_side.end(), side0.begin(), side0.end());
      right_side.insert(right_side.end(), side1.begin(), side1.end());
    }
  const int nleft = left_side.size(), nright = right_side.size();
  vector<long long> left_adj_mask(nleft);
  for (int i = 0; i < nleft; ++i) {
    left_adj_mask[i] = 0LL;
    for (int id : adj[left_side[i]]) {
      int right_pos =
          find(right_side.begin(), right_side.end(), id) - right_side.begin();
      assert(right_pos < (int)right_side.size());
      left_adj_mask[i] |= 1LL << right_pos;
    }
  }
  const int first_half = nleft / 2, second_half = (nleft + 1) / 2;
  vector<long long> first_combined(1 << first_half, 0LL);
  for (int i = 0; i < first_half; ++i)
    first_combined[1 << i] = left_adj_mask[i];
  for (int mask = 1; mask < (1 << first_half); ++mask) {
    int low_bit = mask & -mask;
    if (mask != low_bit) {
      first_combined[mask] =
          first_combined[low_bit] | first_combined[mask ^ low_bit];
    }
  }
  vector<long long> second_combined(1 << second_half, 0LL);
  for (int i = 0; i < second_half; ++i)
    second_combined[1 << i] = left_adj_mask[first_half + i];
  for (int mask = 1; mask < (1 << second_half); ++mask) {
    int low_bit = mask & -mask;
    if (mask != low_bit) {
      second_combined[mask] =
          second_combined[low_bit] | second_combined[mask ^ low_bit];
    }
  }
  const bool ensure_maximal = (nright <= 29);
  vector<bool> seen_right_mask;
  if (ensure_maximal) seen_right_mask.resize(1 << nright, false);
  int final_result = INT_MAX;
  int nmaximal = 0;
  for (int left_mask = (1 << nleft) - 1; left_mask >= 0; --left_mask) {
    long long combined_adj =
        first_combined[left_mask & ((1 << first_half) - 1)] |
        second_combined[left_mask >> first_half];
    long long right_mask = ((1LL << nright) - 1) ^ combined_adj;
    if (ensure_maximal) {
      if (seen_right_mask[right_mask]) continue;
      seen_right_mask[right_mask] = true;
    }
    ++nmaximal;
    twosat_t twosat(ni);
    vector<int> candidates;
    for (int i = 0; i < nleft; ++i)
      if (left_mask & (1 << i)) candidates.push_back(left_side[i]);
    for (int i = 0; i < nright; ++i)
      if (right_mask & (1LL << i)) candidates.push_back(right_side[i]);
    for (int i = 0; i < (int)candidates.size(); ++i) {
      expr_t &expr = l2exprs[candidates[i]];
      expr_t *subs[2] = {expr.sub0, expr.sub1};
      int neutral_value_mask = -1;
      for (int value_mask = 0; value_mask < (1 << 2); ++value_mask) {
        for (int k = 0; k < 2; ++k)
          subs[k]->enforce_value = ((value_mask & (1 << k)) != 0);
        int res_normal = expr.compute_normal();
        int res_changed = expr.compute_changed();
        if (!res_normal && !res_changed) {
          neutral_value_mask = value_mask;
          break;
        }
      }
      for (int k = 0; k < 2; ++k) subs[k]->enforce_value = -1;
      assert(neutral_value_mask != -1);
      for (int k = 0; k < 2; ++k)
        subs[k]->add_constraints(((neutral_value_mask & (1 << k)) != 0),
                                 twosat);
    }
    bool ok = !twosat.solve();
    if (ok) {
      final_result =
          min(final_result, orig_nl2 - (nalways_use + (int)candidates.size()));
    }
  }
  fprintf(stderr, "N maximal: %d\n", nmaximal);
  if (final_result == INT_MAX)
    printf("-1\n");
  else
    printf("%d\n", final_result);
  return 0;
}
