#include<bits/stdc++.h>
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;


struct Info{
	char name[21];
	int table[5];
};

struct Data{
	char name[21];
	int info_index;
};

int num_base,num_assembly,num_variable;
char formula[101];
Info info[10];
Data data[15];
bool error_FLG;


bool is_alpha(char ch){

	if(ch >= 'a' && ch <= 'z')return true;
	if(ch >= 'A' && ch <= 'Z')return true;

	return false;
}

//baseとcompが等しいか比べる関数
bool strCmp(char* base, char* comp){
	int length1,length2;
	for(length1=0;base[length1] != '\0';length1++);
	for(length2=0;comp[length2] != '\0';length2++);
	if(length1 != length2)return false;

	for(int i=0;base[i] != '\0'; i++){
		if(base[i] != comp[i])return false;
	}
	return true;
}

void strcpy(char* to,char* str){
	for(int i=0;str[i] != '\0';i++){
		to[i] = str[i];
		to[i+1] = '\0';
	}
}

vector<int> calc_Formula(int,int);

vector<int> calc_string(int left,int right){

	char work[21];
	int index = 0;

	for(int i = left; i <= right; i++){
		work[index++] = formula[i];
	}
	work[index] = '\0';

	vector<int> ret;

	//該当する変数があるか調べる
	for(int i = 0; i < num_variable; i++){
		if(strCmp(work,data[i].name)){
			for(int k = 0; k < num_base; k++){
				ret.push_back(info[data[i].info_index].table[k]);
			}
			return ret;
		}
	}

	//該当する変数がないならエラー
	error_FLG = true;
	return ret;
}

vector<int> calc_variable(int left,int right){
	return calc_string(left,right);
}

vector<int> calc_Factor(int left,int right){

	if(formula[left] == '('){
		return calc_Formula(left+1,right-1);
	}

	return calc_variable(left,right);
}

vector<int> calc_Term(int left,int right){

	int depth = 0;
	queue<int> Q;

	//深さ0の*,/を探す
	for(int i = left; i <= right; i++){

		if(formula[i] == '('){
			depth++;
		}else if(formula[i] == ')'){
			depth--;
		}else if(depth == 0 && (formula[i] == '*' || formula[i] == '/')){
			Q.push(i);
		}
	}

	if(Q.size() == 0){
		return calc_Factor(left,right);
	}

	vector<int> ret,tmp;

	ret = calc_Term(left,Q.front()-1);
	if(error_FLG)return ret;


	while(!Q.empty()){

		int loc = Q.front();
		Q.pop();

		if(Q.empty()){
			tmp = calc_Factor(loc+1,right);
		}else{
			tmp = calc_Factor(loc+1,Q.front()-1);
		}

		if(error_FLG)return ret;

		//次元の計算を行う(指数の加減算)
		if(formula[loc] == '*'){

			for(int i = 0; i < num_base; i++){
				ret[i] += tmp[i];
			}

		}else{ //割り算

			for(int i = 0; i < num_base; i++){

				ret[i] -= tmp[i];
			}
		}
	}

	return ret;

}

vector<int> calc_Formula(int left,int right){

	int depth = 0;
	queue<int> Q;

	//深さ0の+,-を探す
	for(int i = left; i <= right; ){

		if(formula[i] == '('){
			depth++;
		}else if(formula[i] == ')'){
			depth--;
		}

		if(depth != 0){
			i++;
		}else if(formula[i] != '+' && formula[i] != '-'){
			i++;
		}else{
			if(formula[i] == '+'){
				Q.push(i);
				i++;
			}else{ //line[i] == '-'
				if((i != left) && (is_alpha(formula[i-1]) == true || formula[i-1] == ')')){ //-は、depthが0でもnegの場合あり
					Q.push(i);
				}
				while(i <=right && formula[i] == '-')i++; //negの-が続いている場合があるので、読み飛ばす
			}
		}

	}

	if(Q.size() == 0){
		return calc_Term(left,right);
	}

	vector<int> ret,tmp;

	ret = calc_Formula(left,Q.front()-1);
	if(error_FLG)return ret;


	while(!Q.empty()){

		int loc = Q.front();
		Q.pop();

		if(Q.empty()){
			tmp = calc_Term(loc+1,right);
		}else{
			tmp = calc_Term(loc+1,Q.front()-1);
		}

		if(error_FLG)return ret;

		//2つの次元が違うなら終了
		for(int i = 0; i < num_base; i++){
			if(ret[i] != tmp[i]){
				error_FLG = true;
				return ret;
			}
		}
		//★係数は無視するので演算は行わない★
	}

	return ret;
}

void func(){

	//組み立て量の取得
	for(int i = 0; i < num_assembly; i++){

		scanf("%s",info[i].name);
		for(int k = 0; k < num_base; k++){
			scanf("%d",&info[i].table[k]);
		}
	}

	int length;

	scanf("%s",formula);

	for(length = 0; formula[length] != '\0'; length++);

	char buf[21];

	for(int i = 0; i < num_variable; i++){

		scanf("%s %s",data[i].name,buf);
		for(int k = 0; k < num_assembly; k++){ //組み立て量を探す
			if(strCmp(buf,info[k].name)){
				data[i].info_index = k;
				break;
			}
		}
	}

	error_FLG = false;

	vector<int> ret = calc_Formula(0,length-1);

	if(error_FLG){
		printf("error\n");
		return;
	}

	bool FLG;
	//該当する次元があるか探す
	for(int i = num_assembly-1; i >= 0; i--){
		FLG = true;
		for(int k = 0; k < num_base; k++){
			if(ret[k] != info[i].table[k]){
				FLG = false;
				break;
			}
		}
		if(FLG){
			printf("%s\n",info[i].name);
			return;
		}
	}

	printf("undefined\n");
}

int main(){

	while(true){

		scanf("%d %d %d",&num_base,&num_assembly,&num_variable);
		if(num_base == 0 && num_assembly == 0 && num_variable == 0)break;

		func();
	}

	return 0;
}

