Problem Statement

In the headquarter building of ICPC (International Company of Plugs & Connectors), there are $M$ light bulbs and they are controlled by $N$ switches. Each light bulb can be turned on or off by exactly one switch. Each switch may control multiple light bulbs. When you operate a switch, all the light bulbs controlled by the switch change their states. You lost the table that recorded the correspondence between the switches and the light bulbs, and want to restore it.

You decided to restore the correspondence by the following procedure.

* At first, every switch is off and every light bulb is off.
* You operate some switches represented by $S_1$.
* You check the states of the light bulbs represented by $B_1$.
* You operate some switches represented by $S_2$.
* You check the states of the light bulbs represented by $B_2$.
* ...
* You operate some switches represented by $S_Q$.
* You check the states of the light bulbs represented by $B_Q$.



After you operate some switches and check the states of the light bulbs, the states of the switches and the light bulbs are kept for next operations.

Can you restore the correspondence between the switches and the light bulbs using the information about the switches you have operated and the states of the light bulbs you have checked?

Input

The input consists of multiple datasets. The number of dataset is no more than $50$ and the file size is no more than $10\mathrm{MB}$. Each dataset is formatted as follows.

> $N$ $M$ $Q$
> $S_1$ $B_1$
> :
> :
> $S_Q$ $B_Q$

The first line of each dataset contains three integers $N$ ($1 \le N \le 36$), $M$ ($1 \le M \le 1{,}000$), $Q$ ($0 \le Q \le 1{,}000$), which denote the number of switches, the number of light bulbs and the number of operations respectively. The following $Q$ lines describe the information about the switches you have operated and the states of the light bulbs you have checked. The $i$-th of them contains two strings $S_i$ and $B_i$ of lengths $N$ and $M$ respectively. Each $S_i$ denotes the set of the switches you have operated: $S_{ij}$ is either $0$ or $1$, which denotes the $j$-th switch is not operated or operated respectively. Each $B_i$ denotes the states of the light bulbs: $B_{ij}$ is either $0$ or $1$, which denotes the $j$-th light bulb is off or on respectively.

You can assume that there exists a correspondence between the switches and the light bulbs which is consistent with the given information.

The end of input is indicated by a line containing three zeros.

Output

For each dataset, output the correspondence between the switches and the light bulbs consisting of $M$ numbers written in base-$36$. In the base-$36$ system for this problem, the values $0$-$9$ and $10$-$35$ are represented by the characters '0'-'9' and 'A'-'Z' respectively. The $i$-th character of the correspondence means the number of the switch controlling the $i$-th light bulb. If you cannot determine which switch controls the $i$-th light bulb, output '?' as the $i$-th character instead of the number of a switch.

Sample Input


3 10 3
000 0000000000
110 0000001111
101 1111111100
2 2 0
1 1 0
2 1 1
01 1
11 11 10
10000000000 10000000000
11000000000 01000000000
01100000000 00100000000
00110000000 00010000000
00011000000 00001000000
00001100000 00000100000
00000110000 00000010000
00000011000 00000001000
00000001100 00000000100
00000000110 00000000010
0 0 0

Output for the Sample Input


2222221100
??
0
1
0123456789A





Example

Input

3 10 3
000 0000000000
110 0000001111
101 1111111100
2 2 0
1 1 0
2 1 1
01 1
11 11 10
10000000000 10000000000
11000000000 01000000000
01100000000 00100000000
00110000000 00010000000
00011000000 00001000000
00001100000 00000100000
00000110000 00000010000
00000011000 00000001000
00000001100 00000000100
00000000110 00000000010
0 0 0


Output

2222221100
??
0
1
0123456789A
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.ArrayIndexOutOfBoundsException;
import java.math.BigInteger;

import javax.script.AbstractScriptEngine;


/**
 * @author yoshikyoto
 */
class Main extends MyUtil{
	// public static Graph g;
	
	public static void main(String[] args) throws Exception{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		while(true){
			String[] in = br.readLine().split(" ");
			int n = Integer.parseInt(in[0]);
			int m = Integer.parseInt(in[1]);
			int q = Integer.parseInt(in[2]);
			if(n == 0 && m == 0 && q == 0) break;
			

			Long bit_fill0 = 0L;
			Long bit_fill1 = 0L;
			for(int i = 0; i< n; i++)
				bit_fill1 = (bit_fill1<<1) | 1L;
			
			// フラグの初期化
			long[] bit = new long[m];
			for(int i = 0; i < m; i++) 
				bit[i] = bit_fill1;
			
			long state = bit_fill0;
			for(int i = 0; i < q; i++){
				in = br.readLine().split(" ");
				String s = in[0];
				String b = in[1];
				long sb = Long.parseLong(s, 2);
				// 状態の更新
				state = state ^ sb;
				// System.out.println(Long.toBinaryString(state));
				
				for(int j = 0; j < m; j++){
					int flag = b.charAt(j) - '0';
					if(flag == 1){
						// 電気がついた場合は、今1になったスイッチのどれかとつながっている
						bit[j] = bit[j] & state;
					}else{
						// 電気がついてない場合は、今0のスイッチのどれかとと長っている
						bit[j] = bit[j] & ~state;
					}
				}
			}
			
			StringBuffer ans = new StringBuffer("");
			for(int i = 0; i < m; i++){
				if(Long.bitCount(bit[i]) == 1){
					// 立っているbitが1つの場合
					// それが答えなので36進数に変換してやる
					int snum = n - 1 - Long.numberOfTrailingZeros(bit[i]);
					ans.append(toChar(snum));
				}else{
					// そうでない場合はわからない
					ans.append('?');
				}
			}
			System.out.println(ans.toString());
		}
	}

	static char toChar(int i){
		if(i < 10){
			return (char)('0' + i);
		}else{
			return (char)('A' + (i - 10));
		}
	}
}


// --- ここから下はライブラリ ----------
 
class ArrayComp implements Comparator<int[]>{
	public int compare(int[] a, int[] b){
		int l = Math.min(a.length, b.length);
		for(int i = 0; i < l; i++){
			if(a[i] == b[i]) continue;
			return a[i] - b[i];
		}
		return 0;
	}
}
 
class Node extends ArrayList<Edge>{
	int index, depth = -1, dist = -1;
	Node(int index){this.index = index;}
	Node parent;
	boolean visited = false;
}
class Edge{
	int from, to, cost;
	Edge(int from, int to, int cost){
		this.from = from;
		this.to = to;
		this.cost = cost;
	}
}
class NodeComparator implements Comparator<Node>{
	public int compare(Node a, Node b){
		return a.dist - b.dist;
	}
}
 
class Graph{
	Node n[];
	Graph(int node_count){
		n = new Node[node_count];
		for(int i = 0; i < node_count; i++) n[i] = new Node(i);
	}
	public void add(Edge e){
		n[e.from].add(e);
	}
	public Node get(int i){return n[i];}
	public Node lca(int a, int b){
		// 浅い方をaとする
		Node nodeA, nodeB;
		if(n[a].depth < n[b].depth){
			nodeA = n[a];
			nodeB = n[b];
		}else{
			nodeA = n[b];
			nodeB = n[a];
		}
		// 同じ深さまで親をたどる
		int diff = nodeB.depth - nodeA.depth;
		for(int k = 0; k < diff; k++){
			nodeB = nodeB.parent;
		}
		// 共通祖先を見つける
		while(nodeA != nodeB){
			nodeA = nodeA.parent;
			nodeB = nodeB.parent;
		}
		return nodeA;
	}
	public void calcDepth(int root){
		ArrayDeque<Integer> que = new ArrayDeque<Integer>();
		que.push(root);
		n[root].depth = 0;
 
		while(que.size() > 0){
			int curr = que.pop();
			Node curr_node = n[curr];
			for(Edge e : curr_node){
				int next = e.to;
				Node next_node = n[next];
				if(next_node.depth == -1){
					next_node.depth = curr_node.depth + 1;
					next_node.parent = curr_node;
					que.push(next);
				}
			}
		}
	}
 
	public int[] dijkstra(int s){
		PriorityQueue<Node> q = new PriorityQueue<Node>(n.length, new NodeComparator());
		Node start_node = new Node(s);
		start_node.dist = 0;
		q.add(start_node);
		int[] dist = new int[n.length];
		for (int i = 0; i < dist.length; i++)  dist[i] = -1;
		dist[s] = 0;
 
		while(q.size() > 0){
			Node currNode = q.poll();
			if(dist[currNode.index] < currNode.dist) continue;
			for(Edge e : n[currNode.index]){
				Node nextNode = new Node(e.to);
				nextNode.dist = currNode.dist + e.cost;
				if(dist[e.to] == -1 || dist[e.to] > nextNode.dist){
					dist[e.to] = nextNode.dist;
					q.add(nextNode);
				}
			}
		}
		return dist;
	}
}
 
 
 
class Regex{
	Pattern p; Matcher m; String str;
	Regex(String regex_str){p = Pattern.compile(regex_str);}
	void setStr(String str){m = p.matcher(str);}
	boolean find(){return m.find();}
	String group(int i){return m.group(i);}
	String group(){return m.group();}
}
 
/**
 * UnionFindTree 
 * @author yoshikyoto
 */
class UnionFindTree{
	public int[] parent, rank;
	public int n;
	public int count;
	// 初期化
	UnionFindTree(int n){
		this.n = n;
		count = n;
		parent = new int[n];
		rank = new int[n];
		for(int i = 0; i < n; i++){
			parent[i] = i;
			rank[i] = 0;
		}
	}
	// 根を求める
	int find(int x){
		if(parent[x] == x){
			return x;
		}else{
			return parent[x] = find(parent[x]);
		}
	}
	// xとyの集合を結合
	void unite(int x, int y){
		x = find(x);
		y = find(y);
		if(x == y){
			return;
		}
		if(rank[x] < rank[y]){
			parent[x] = y;
			count--;
		}else{
			parent[y] = x;
			if(rank[x] == rank[y]) rank[x]++;
			count--;
		}
	}
	// xとyが同じ集合か
	boolean same(int x, int y){
		return find(x) == find(y);
	}
};
 
 

 
class CountHashMap<E> extends HashMap<E, Integer>{
	ArrayList<E> keyArray = new ArrayList<E>();
	public void add(E key){add(key, 1);}
	public void add(E key, Integer value){
		if(containsKey(key)){value += get(key);
		}else{keyArray.add(key);}
		put(key, value);
	}
}
 
/**
 * MyUtil
 * @author yoshikyoto
 */
class MyUtil extends MyIO{
	public static Random rand = new Random();
	public static int digit(int n){return String.valueOf(n).length();}
	public static String reverse(String s){return (new StringBuffer(s)).reverse().toString();}
	public static void dsort(int[] a){
		Arrays.sort(a);
		int l = a.length;
		for(int i = 0; i < l/2; i++){
			int tmp = a[i]; a[i] = a[l-1-i]; a[l-1-i] = tmp;
		}
	}
	public static void sleep(int t){try{Thread.sleep(t);}catch(Exception e){}}
	public static int sum(int[] a){int s = 0; for(int i = 0; i < a.length; i++)s+=a[i]; return s;}
	public static int[] cp(int[] a){
		int[] b = new int[a.length];
		for(int i = 0; i < a.length; i++) b[i] = a[i];
		return b;
	}
	public static int randomInt(int min, int max){return min + rand.nextInt(max - min + 1);}
	static boolean inside(int y, int x, int h, int w){return 0 <= y && y <= (h-1) && 0 <= x && x <= (w-1);};
	public static boolean isUpper(char c){return 'A'<=c&&c<='Z';}
	public static boolean isLower(char c){return 'a'<=c&&c<='z';}
	public static char toUpper(char c){
		if(isLower(c)) return (char)(c - 'a' + 'A');
		return c;
	}
	public static char toLower(char c){
		if(isUpper(c)) return (char)(c - 'A' + 'a');
		return c;
	}
	public static int[] swap(int[] arr, int i, int j){
		int[] ret = cp(arr);
		int tmp = ret[i];
		ret[i] = ret[j];
		ret[j] = tmp;
		return ret;
	}
	public static int toInt(boolean[] a){
		int pow = 1, ret = 0, l = a.length;
		for(int i = 0; i < l; i++){
			if(a[i]) ret += pow;
			pow *= 2;
		}
		return ret;
	}
}
 
/**
 * MyIO
 * @author yoshikyoto
 */
class MyIO extends MyMath{
	static Scanner sc = new Scanner(new InputStreamReader(System.in));
	public static char scNextChar(){return sc.next().charAt(0);}
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	public static String line;
 
	public static int ins[];
	public static int[] readIntMap() throws IOException{return parseInt(readLine().split(" "));}
	public static int readIntMap(int i) throws Exception{
		if(i == 0) ins = readIntMap();
		return ins[i];
	}
	public static int[][] readIntMap(int n, int m) throws IOException{
		int[][] ret = new int[n][];
		for(int i = 0; i < n; i++) ret[i] = readIntMap();
		return ret;
	}
	public static int[] readIntToMap(int n) throws IOException{
		int[] ret = new int[n];
		for(int i = 0; i < n; i++) ret[i] = readInt();
		return ret;
	}
	public static int[] readNoDistIntMap() throws IOException{
		String[] strs = readLine().split("");
		int l = strs.length;
		int[] ret = new int[l-1];
		for(int i = 1; i < l; i++)
			ret[i-1] = parseInt(strs[i]);
		return ret;
	}
	public static boolean readToLine() throws IOException{return (line = br.readLine()) != null;}
	public static String readLine() throws IOException{return br.readLine();}
	public static int readInt() throws IOException{return Integer.parseInt(br.readLine());}
	public static int[] parseInt(String[] arr){
		int[] res = new int[arr.length];
		for(int i = 0; i < arr.length; i++)res[i] = Integer.parseInt(arr[i]);
		return res;
	}
	public static double[] parseDouble(String[] arr){
		double[] res = new double[arr.length];
		for(int i = 0; i < arr.length; i++)res[i] = Double.parseDouble(arr[i]);
		return res;
	}
	public static boolean[] parseBool(String[] arr){
		int[] t = parseInt(arr);
		boolean[] res = new boolean[t.length];
		for(int i = 0; i < t.length; i++){
			if(t[i] == 1){res[i] = true;
			}else{res[i] = false;}
		}
		return res;
	}
	public static int parseInt(Object o){return Integer.parseInt(o.toString());}
}
 
class MyMath{
	public static int max(int[] arr){return max(arr, 0, arr.length-1);}
	public static int max(int[] arr, int l, int r){
		int max = arr[l];
		for(int i = l+1; i <= r; i++)
			max = Math.max(max, arr[i]);
		return max;
	}
	public static int min(int[] arr){return min(arr, 0, arr.length-1);}
	public static int min(int[] arr, int l, int r){
		int min = arr[l];
		for(int i = l+1; i <= r; i++)
			min = Math.min(min, arr[i]);
		return min;
	}
	public static boolean isCross(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
		// 並行な場合
		int m = (x2-x1)*(y4-y3)-(y2-y1)*(x4-x3);
		if(m == 0) return false;
		// 媒介変数の値が0より大きく1以下なら交差する、これは問題の状況によって変わるかも。
		double r =(double)((y4-y3)*(x3-x1)-(x4-x3)*(y3-y1))/m;
		double s =(double)((y2-y1)*(x3-x1)-(x2-x1)*(y3-y1))/m;
		return (0 < r && r <= 1 && 0 < s && s <= 1);
	}
	public static boolean isParallel(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4){
		if((x2-x1)*(y4-y3) == (y2-y1)*(x4-x3)) return true;
		else return false;
	}
	public static double sq(double d){return d*d;}
	public static int sq(int i){return i*i;}
	public static int sqdist(int x1, int y1, int x2, int y2){return (x1-x2) + sq(y1-y2);}
	public static double sqdist(double x1, double y1, double x2, double y2){return sq(x1-x2) + sq(y1-y2);}
	public static double dist(int x1, int y1, int x2, int y2){return Math.sqrt(sqdist(x1, y1, x2, y2));}
	public static double dist(double x1, double y1, double x2, double y2){return Math.sqrt(sqdist(x1, y1, x2, y2));}
	static long comb(long n, long m){
		if(n < m) return 0;
		long c = 1; m = (n - m < m ? n - m : m);
		for(long ns = n - m + 1, ms = 1; ms <= m; ns ++, ms ++){c *= ns; c /= ms;}
		return c;
	}
	static int gcd(int a, int b){if(a%b==0){return(b);}else{return(gcd(b,a%b));}};
	/**
	 * aの中から、合計がborderを超えるペア（重複除く）の数を数える
	 */
	static int countPair(int[] a, int border){
		int count = 0, l = a.length, i = 0, j = l-1;
		for (; i < l; i++) {
			for (; j >= 0; j--) if(a[i] + a[j] <= border) break;
			count += l - (j + 1);
			if(j < i) count--;
		}
		return count/2;
	}
	// modに対応したDPのCombination
	static int mcomb(int n, int m, int mod){
		n = n - m;
		int[][] dp = new int[n+1][m+1];
		for(int i = 0; i <= n; i++) dp[i][0] = 1;
		for(int i = 0; i <= m; i++) dp[0][i] = 1;
		// mod = 0 の時は余りを取らない
		if(mod != 0){
			for(int i = 1; i <= n; i++){
				for(int j = 1; j <= m; j++){
					dp[i][j] = (dp[i-1][j] + dp[i][j-1]);
				}
			}
			return dp[n][m];
		// それ以外の時は mod をとっていく
		}else{
			for(int i = 1; i <= n; i++){
				for(int j = 1; j <= m; j++){
					dp[i][j] = (dp[i-1][j] + dp[i][j-1]) % mod;
				}
			}
			return dp[n][m] % mod;
		}
	}
	

	static long mcomb(int n, int m, long mod){
		n = n - m;
		long[][] dp = new long[n+1][m+1];
		for(int i = 0; i <= n; i++) dp[i][0] = 1;
		for(int i = 0; i <= m; i++) dp[0][i] = 1;
		// mod = 0 の時は余りを取らない
		if(mod != 0){
			for(int i = 1; i <= n; i++){
				for(int j = 1; j <= m; j++){
					dp[i][j] = (dp[i-1][j] + dp[i][j-1]);
				}
			}
			return dp[n][m];
		// それ以外の時は mod をとっていく
		}else{
			for(int i = 1; i <= n; i++){
				for(int j = 1; j <= m; j++){
					dp[i][j] = (dp[i-1][j] + dp[i][j-1]) % mod;
				}
			}
			return dp[n][m] % mod;
		}
	}
}