Problem: The dimension of quantity is a concept that ignores concrete numerical values ​​from the relational expressions between different quantities and focuses only on the type of quantity and its power. Specifically, the relational expression of the dimension is expressed as an equation ignoring the constant coefficient. That is, if the dimension of the quantity q is expressed as [q], the following relational expressions of several dimensions can be exemplified.

* [Area] = [Length] 2
* [Volume] = [Length] 3
* [Speed] = [Length] [Time] -1
* [Acceleration] = [Length] [Time] -2
* [Force] = [Mass] [Length] [Time] -2
* [Work] = [Mass] [Length] 2 [Time] -2



(Excerpt from Wikipedia "Quantity" URL http://ja.wikipedia.org/wiki/%E9%87%8F)

The amount is classified into the basic amount and the assembled amount. In this problem, n basic quantities and m assembly quantities are given. The dimensions of a given m assembly can all be represented by the product of n base unit dimensions. Also, when two dimensions are represented by the product of the dimensions of the basic quantities, it can be said that the two dimensions are equal if all the indices of the basic quantities match.

Given information about the quantity of expressions and variables and the dimension of the quantity, analyze the equation and output the name of the quantity represented by that dimension. If the name is not defined, output undefined. In addition, an operation that adds or subtracts two different dimensions in the calculation process is defined as an "illegal operation". If there is an "illegal operation", output error. The given equation satisfies:

1. All variables are assigned to the assembly dimension.
2. The expression contains only four arithmetic operations +,-, /, *, parentheses () and variables.
3. The four arithmetic operations are well known and shall be described correctly. Strictly speaking, it follows the following BNF. Also, unary operators are not used. There is no such thing as (x * (-a)).




<formula> :: = <term> | <formula> + <term> | <formula>-<term>
<term> :: = <factor> | <term> * <factor> | <term> / <factor>
<factor> :: = <variable> | (<formula>)
<variable> :: = <string>
<string> :: = <char> | <string> <char>
<char> :: = a ~ z | A ~ Z
<formula> represents an expression and <variable> represents a variable name.




Input

The input consists of multiple datasets. The number of datasets does not exceed 1,000. The dataset is given in the following format.


n m p
derived1
d1,1 d1,2 d1,3 .... d1, n
derived2
d2,1 d2,2 d2,3 .... d2, n
...
derivedm
dm, 1 dm, 2 dm, 3 .... dm, n
formula
v1 D1
v2 D2
...
vp Dp


n (1 ≤ n ≤ 5) is the number of basic quantities m (1 ≤ m ≤ 10) is the number of assemblies p (1 ≤ p ≤ 15) is the number of variable types. derivedi is the name of the i-th assembly. It is composed of uppercase and lowercase letters and does not exceed 20 characters in length. di, j (-10 ≤ di, j ≤ 10) represents the dimension of the j-th basic quantity of the i-th assembly (1 ≤ i ≤ m, 1 ≤ j ≤ n). The name of the same assembly does not appear multiple times. The assembly quantity of the same dimension may appear multiple times, in which case the last defined name will be the name of the assembly quantity. formula represents the formula to be analyzed. The length does not exceed 100 characters. vi represents a variable name. It is composed of uppercase and lowercase letters and does not exceed 20 characters in length. Di represents the name of the dimension of vi. It is guaranteed to be the name of the assembly already given. The numbers you are typing (n, m, p, d) are all integers. The end of the input is indicated by a line where each of the three 0s is separated by a single character space.

Output

Analyze the formula in one line and output the name of the dimension. If the name is not defined, output undefined. Also, if an invalid operation is included, output error.

Example

Input

2 3 2
length
1 0
time
0 1
speed
1 -1
a/b
a length
b time
2 3 3
length
1 0
time
0 1
speed
1 -1
a/b+c
a length
b time
c speed
2 3 3
length
1 0
time
0 1
speed
1 -1
a/b+c
a length
b time
c time
2 3 2
length
1 0
time
0 1
speed
1 -1
a/b/b
a length
b time
3 6 6
speed
1 -1 0
acceleration
1 -2 0
force
1 -2 1
length
1 0 0
time
0 1 0
weight
0 0 1
((v+l/t)+a*t)/(t*t)*w*t+f+w*a
v speed
l length
a acceleration
t time
w weight
f force
0 0 0


Output

speed
speed
error
undefined
force

Solution (in CPP):

Solution:
#include <map>
#include <iostream>
#include <queue>
#include <sstream>
#include <cstdio>
#define REP(i,n) for(int i=0; i<(int)(n); i++)

using namespace std;

enum{
  BINARY_OPERATOR = 0,
  UNARY_OPERATOR  = 1,
  VALUE           = 2
};

struct Tree{
  int type;

  // Identifier, Value or Operator
  string s;

  struct Tree *left;
  struct Tree *right;

  Tree(int t, const string &v, Tree *l = NULL, Tree *r = NULL)
    : type(t), s(v), left(l), right(r) {}

  Tree(int t, char v, Tree *l = NULL, Tree *r = NULL)
    : type(t), left(l), right(r) {
    stringstream ss; ss << v;
    s = ss.str();
  }

  void debug(){
    cout << "(";
    switch(type){
    case BINARY_OPERATOR:
      left->debug();
      cout << s;
      right->debug();
      break;
    case UNARY_OPERATOR:
      cout << s;
      left->debug();
      break;
    case VALUE:
      cout << s;
      break;
    }
    cout << ")";
  }
};

struct Parser{
  const string bop1;
  const string bop2;
  const string uop;

  Parser(const string &b1 = "+-",
         const string &b2 = "*/",
         const string &u = "-")
    : bop1(b1), bop2(b2), uop(u) {}

  typedef pair<Tree *, const char *> P;

  P parseExpr(const char *p) const{
    P r = parseTerm(p);
    while( *r.second != '\0' && bop1.find(*r.second) != string::npos ){
      char op   = *r.second;
      Tree *tmp = r.first;
      r = parseTerm(r.second + 1);
      r.first = new Tree(BINARY_OPERATOR, op, tmp, r.first);
    }
    return r;
  }

  P parseTerm(const char *p) const{
    P r = parseFact(p);
    while( *r.second != '\0' && bop2.find(*r.second) != string::npos ){
      char op   = *r.second;
      Tree *tmp = r.first;
      r = parseFact(r.second + 1);
      r.first = new Tree(BINARY_OPERATOR, op, tmp, r.first);
    }
    return r;
  }

  P parseFact(const char *p) const{
    if(uop.find(*p) != string::npos){
      P r = parseFact(p + 1);
      return P(new Tree(UNARY_OPERATOR, *p, r.first), r.second);
    }else if(*p == '('){
      P r = parseExpr(p + 1);
      if(*r.second != ')') throw make_pair("fact1", p);
      return P(r.first, r.second + 1);
    }else{
      // identifier or value
      int i = 0;
      char buff[256];
      while(*p != '\0' &&
            bop1.find(*p) == string::npos &&
            bop2.find(*p) == string::npos &&
            uop.find(*p)  == string::npos &&
            *p != '(' && *p != ')'){
        buff[i++] = *p++;
      }
      buff[i] = '\0';
      if(i == 0) throw make_pair("fact2", p);
      return P(new Tree(VALUE, string(buff)), p);
    }
  }

  Tree *parse(const string &str) const{
    return parseExpr(str.c_str()).first;
  }
};

int n, m, p;
int d[10][10];
map<string, int> var;

vector<int> check(Tree *t){
  vector<int> ret(n);

  if(t->type == BINARY_OPERATOR){
    vector<int> l = check(t->left);
    vector<int> r = check(t->right);

    if(t->s == "+" || t->s == "-"){
      REP(i,n) if(l[i] != r[i]) throw 0;
      ret = l;
    }else if(t->s == "*"){
      REP(i,n) ret[i] = l[i] + r[i];
    }else if(t->s == "/"){
      REP(i,n) ret[i] = l[i] - r[i];
    }else{
      while(true);
    }

  }else if(t->type == UNARY_OPERATOR){
    ret = check(t->left);
  }else{
    while(var.count(t->s) == 0);
    int id = var[t->s];
    REP(i,n) ret[i] = d[id][i];
  }

  return ret;
}

void f(Tree *t){
  if(t){
    if(t->left) f(t->left);
    if(t->left) f(t->right);
    delete t;
  }
}

int main(){
  while(cin >> n >> m >> p, n + m + p){
    map<string, int> idm;
    vector<string> deriv(m);

    REP(i,m){
      cin >> deriv[i];
      idm[deriv[i]] = i;
      REP(j,n) cin >> d[i][j];
    }

    string formula; cin >> formula;
    Tree *t = Parser().parse(formula);

    var.clear();
    REP(i,p){
      string a, b; cin >> a >> b;
      var[a] = idm[b];
    }

    try{
      vector<int> ret = check(t);

      for(int i = m - 1; i >= 0; i--){
        bool ok = true;
        REP(j,n) if(ret[j] != d[i][j])
          ok = false;
        if(ok){
          cout << deriv[i] << endl;
          goto end;
        }
      }

      cout << "undefined" << endl;
    end:;
    }catch(...){
      cout << "error" << endl;
    }

    f(t);
  }
  return 0;
}