Developers often face with regular expression patterns. A pattern is usually defined as a string consisting of characters and metacharacters that sets the rules for your search. These patterns are most often used to check whether a particular string meets the certain rules.

In this task, a pattern will be a string consisting of small English letters and question marks ('?'). The question mark in the pattern is a metacharacter that denotes an arbitrary small letter of the English alphabet. We will assume that a string matches the pattern if we can transform the string into the pattern by replacing the question marks by the appropriate characters. For example, string aba matches patterns: ???, ??a, a?a, aba.

Programmers that work for the R1 company love puzzling each other (and themselves) with riddles. One of them is as follows: you are given n patterns of the same length, you need to find a pattern that contains as few question marks as possible, and intersects with each of the given patterns. Two patterns intersect if there is a string that matches both the first and the second pattern. Can you solve this riddle?

Input

The first line contains a single integer n (1 ≤ n ≤ 105) — the number of patterns. Next n lines contain the patterns.

It is guaranteed that the patterns can only consist of small English letters and symbols '?'. All patterns are non-empty and have the same length. The total length of all the patterns does not exceed 105 characters.

Output

In a single line print the answer to the problem — the pattern with the minimal number of signs '?', which intersects with each of the given ones. If there are several answers, print any of them.

Examples

Input

2
?ab
??b


Output

xab


Input

2
a
b


Output

?


Input

1
?a?b


Output

cacb

Note

Consider the first example. Pattern xab intersects with each of the given patterns. Pattern ??? also intersects with each of the given patterns, but it contains more question signs, hence it is not an optimal answer. Clearly, xab is the optimal answer, because it doesn't contain any question sign. There are a lot of other optimal answers, for example: aab, bab, cab, dab and so on.



import java.awt.List;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Queue;
import java.util.Scanner;
import java.util.Set;
import java.util.Stack;
import java.util.*;


 
 
public class cool {

	private static InputStream stream;
	private static PrintWriter pw;
	
	
	
//	static int a;
//	static int b;
//	static int f = 0;
	static int n;
	static int m;
//	static int[][] arr;
	//static char[][] arr;
	
	static int Arr[];
	static int size[];
	
	static int time = 0;
	
	static int[][] dir = {{-1,0},{0,1},{1,0},{0,-1}};

	static int visited[][];
	static int visited2[][];
	static Stack<Integer> stack;
	
//	static ArrayList<Integer> ans;

//	static int arr[][];
//	static int arr[];
	static char[][] arr;
	static char[][] ans;
//	static int[][] visited;
//  static int c;
//	static int d[];
//	static int arr[][];
	static ArrayList[] adj;
//	static ArrayList<Integer> ans;
//	static int f;
	static int parent[];
	static int color[];
//	static ArrayList<Integer> comp[];

	static int f = 0;
	static int k = 0;
	static int count = 0;
	static int ini[];
	
	static ArrayList<Node> list;
	static ArrayList<Integer> ind;
	
	
	
	public static void main(String[] args){
		//InputReader(System.in);
		pw = new PrintWriter(System.out);
		
		Scanner in = new Scanner(System.in);
		
		int n = in.nextInt();
		in.nextLine();
	
		
		char s[] = in.nextLine().toCharArray();
		int arr[] = new int[s.length];
		
		for(int i = 1 ;i<n;i++){
			
			String a = in.nextLine();

			for(int j = 0;j<a.length();j++){
				if(arr[j] == 0){
					if(s[j] == '?' && a.charAt(j) != '?'){
						s[j] = a.charAt(j);
					}else if(s[j] != '?' && a.charAt(j) != '?' && s[j] != a.charAt(j)){
						arr[j] = 1;
						s[j] = '*';
					}
				}
			}
				
			
			
			
			
		}
		
		for(int i = 0;i<s.length;i++){
			if(s[i] == '*'){
				s[i] = '?';
			}else if(s[i] == '?'){
				s[i] = 'a';
			}
		}
		
		System.out.println(String.copyValueOf(s));
		
		//pw.close();
	}

	public static boolean[] sieveOfEratosthenes(int n)
    {
        
        boolean prime[] = new boolean[n+1];
        for(int i=0;i<n;i++)
            prime[i] = true;
         
        for(int p = 2; p*p <=n; p++)
        {
            
            if(prime[p] == true)
            {
                for(int i = p*2; i <= n; i += p)
                    prime[i] = false;
            }
        }
       
       
        return prime;
    }
	
	public static void dfs(int i,int j){
		//pw.println(i + " " + j);
		//System.out.println(i + " " + j);
		if(visited[i][j] == 1)
			return;
		
		if(arr[i][j] == '*')
			return;
		
		visited[i][j] = 1;
		
		count++;
		//System.out.println(i + " "+ j);
		
		for(int p = 0;p<4;p++){
			int x = i + dir[p][0];
			int y = j + dir[p][1];
			//.out.println(n + " " + m);
			
			if(x == n || x == -1 || y == m || y == -1){
				//fooled ya..
			}else{
				//.out.println(i+ " " + j + " " + x + " " + y);
				dfs(x,y);
			}
			
			
			
		}
	}
	
	
	
	
	public static int prev(int i,boolean[] arr){
		
		while(arr[i]){
			if(i == 0){
				if(arr[i]){
					return -1;
				}else{
					return 0;
				}
				
				
			}
			
			
			i--;
			
		}
		
		return i;
		
		
	}
	
	
	public static int next(int i,boolean[] arr){
		
		
		while(arr[i]){
			if(i == arr.length-1){
				if(arr[i]){
					return -1;
				}else{
					return 0;
				}
			}
			
			i++;
		}
		
		
		return i;
	}
	

	
	private static Map<String, Integer> sortByValue(Map<String, Integer> unsortMap) {

        // 1. Convert Map to List of Map
        LinkedList<Entry<String, Integer>> list =
                new LinkedList<Map.Entry<String, Integer>>(unsortMap.entrySet());

        // 2. Sort list with Collections.sort(), provide a custom Comparator
        //    Try switch the o1 o2 position for a different order
        Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
            public int compare(Map.Entry<String, Integer> o1,
                               Map.Entry<String, Integer> o2) {
                return (o1.getValue()).compareTo(o2.getValue());
            }
        });

        // 3. Loop the sorted list and put it into a new insertion order Map LinkedHashMap
        Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
        for (Map.Entry<String, Integer> entry : list) {
            sortedMap.put(entry.getKey(), entry.getValue());
        }

        /*
        //classic iterator example
        for (Iterator<Map.Entry<String, Integer>> it = list.iterator(); it.hasNext(); ) {
            Map.Entry<String, Integer> entry = it.next();
            sortedMap.put(entry.getKey(), entry.getValue());
        }*/


        return sortedMap;
    }

	
	public static ArrayList<Integer> Range(int[] numbers, int target) {
	  

	    int low = 0, high = numbers.length - 1;
	    // get the start index of target number
	    int startIndex = -1;
	    while (low <= high) {
	        int mid = (high - low) / 2 + low;
	        if (numbers[mid] > target) {
	            high = mid - 1;
	        } else if (numbers[mid] == target) {
	            startIndex = mid;
	            high = mid - 1;
	        } else
	            low = mid + 1;
	    }

	    // get the end index of target number
	    int endIndex = -1;
	    low = 0;
	    high = numbers.length - 1;
	    while (low <= high) {
	        int mid = (high - low) / 2 + low;
	        if (numbers[mid] > target) {
	            high = mid - 1;
	        } else if (numbers[mid] == target) {
	            endIndex = mid;
	            low = mid + 1;
	        } else
	            low = mid + 1;
	    }

	    ArrayList<Integer> list = new ArrayList<Integer>();
	    int c = 0;
	    if (startIndex != -1 && endIndex != -1){
	        for(int i = startIndex;i<=endIndex;i++){
	        	list.add(i);
	        }
	    }
	    
	    
	    return list;
	    
	    
	}

	
	
	 private static int root(int Arr[],int i)
	    {
	        while(Arr[ i ] != i)           //chase parent of current element until it reaches root
	        {
	            Arr[ i ] = Arr[ Arr[ i ] ] ; 
	            i = Arr[ i ];
	        }
	        return i;
	    }
	 
	 private static void union(int Arr[],int size[],int A,int B)
	    {
	        int root_A = root(Arr,A);
	        int root_B = root(Arr,B);
	     
	       System.out.println(root_A + " " + root_B);
	        if(root_A != root_B){
	        	 if(size[root_A] < size[root_B ])
	 	        {
	        		 Arr[ root_A ] = Arr[root_B];
	        		 size[root_B] += size[root_A];	 	
	 	        }
	 	        else
	 	        {   	
	 	        	Arr[ root_B ] = Arr[root_A];
	 	        	size[root_A] += size[root_B];	 	   
	 	        }	
	        }
	    }
	 
	 private static boolean find(int A,int B)
	    {
	        if( root(Arr,A)==root(Arr,B) )       //if A and B have the same root, it means that they are connected.
	        return true;
	        else
	        return false;
	    }
	 
	
	


//	
//	public static void bfs(int i){
//		
//		Queue<Integer> q=new LinkedList<Integer>();
//    	q.add(i);
//    	
//    	visited[i] = 1;
//    	c++;
//    	nodes++;
//    	while(!q.isEmpty()){
//    		int top=q.poll();
//    		
//    		Iterator<Integer> it= arr[top].listIterator();
//    		while(it.hasNext()){
//    			int next =it.next();
//    			
//    			if(visited[next] == 0){
//    				nodes++;
//    				visited[next] = 1;
//    				q.add(next);
//    			}
//    		
//    		}
//    	}
//		
//	}
	
	
	
//	public static void dfs(int i){
//		
//		
//		if(visited[i] == 1){
//			return;
//		}
//		
//		visited[i] = 1;
//		con[c].add(i);
//		//System.out.print(i + " ");
//		for(int j = 0;j<arr[i].size();j++){
//			dfs(arr[i].get(j));
//		}
//		
//	}
//	
//	
//	public static void dfss(int i){
//		if(visited[i] == 1){
//			return;
//		}
//		
//		visited[i] = 1;
//		
//		for(int j = 0;j<arr[i].size();j++){
//			dfss(arr[i].get(j));
//		}
//	//	System.out.println(i);
//		stack.push(i);
//	}
//	
//	public static void reverse(){
//		ArrayList[] temp = new ArrayList[n];
//		
//		for(int i = 0;i<n;i++){
//			temp[i] = new ArrayList();
//		}
//		
//		for(int i = 0;i<n;i++){
//			for(int j = 0;j<arr[i].size();j++){
//				temp[arr[i].get(j)].add(i);
//			}
//		}
//		
//		arr = temp;
//		
//	}
//	
//	
	
	
	
	
	
	
	public static boolean isPrime(int n) {
		// Corner cases
		if (n <= 1)
			return false;
		if (n <= 3)
			return true;
 
		// This is checked so that we can skip 
		// middle five numbers in below loop
		if (n % 2 == 0 || n % 3 == 0)
			return false;
 
		for (int i = 5; i * i <= n; i = i + 6)
			if (n % i == 0 || n % (i + 2) == 0)
				return false;
 
		return true;
	}
	
		 
	 // union code starts	
	
	
	 
	 // union code ends
	
	
	 
//	 // Segment tree code begins
//	 
//	 
//	 static void build(int node,int start,int end)
//	 {
//	 if(start==end)
//	 tree[node]=a[start];
//	 else
//	 {
//	 int mid=(start+end)/2;
//	 build(2*node,start,mid);
//	 build(2*node+1,mid+1,end);
//	 if(tree[2*node]<tree[2*node+1])
//	 tree[node]=tree[2*node];
//	 else
//	 tree[node]=tree[2*node+1];
//	 }
//	 }
//	 
//	 
//	 static void update(int node,int start,int end,int idx,int val)
//	 {
//	 if(start==end)
//	 {
//	 a[idx]=val;
//	 tree[node]=val;
//	 }
//	 else
//	 {
//	 int mid=(start+end)/2;
//	 if(idx>=start&&idx<=mid)
//	 update(2*node,start,mid,idx,val);
//	 else
//	 update(2*node+1,mid+1,end,idx,val);
//	 if(tree[2*node]<tree[2*node+1])
//	 tree[node]=tree[2*node];
//	 else
//	 tree[node]=tree[2*node+1];
//	 }
//	 }
//	 
//	 static int query(int node,int start,int end,int l,int r)
//	 {
//	 if(l>end||start>r)
//	 return 100005;
//	 if(l<=start&&r>=end)
//	 return tree[node];
//	 int p1,p2;
//	 int mid=(start+end)/2;
//	 p1=query(2*node,start,mid,l,r);
//	 p2=query(2*node+1,mid+1,end,l,r);
//	 if(p1<p2)
//	 return p1;
//	 else
//	 return p2;
//	 }
//	 
//	 
//	 
//}

}

class Node{
	point a;
	int b;
}

class point{
	int a;
	int b;
}


class MyComp2 implements Comparator<Node>{
    
	@Override
	public int compare(Node o1, Node o2) {
		
//		if((o1.b - o2.b) < 0.00000001){
//			return 0;
//		}else 
		if(o1.b == o2.b){
			return 0;
		}else if( o1.b > o2.b){
			return 1;
		}else if( o2.b > o1.b){
			return -1;
		}
		return 0;
		
	}
}


class Card implements Comparable<Card>
{
	int a,b;
	public Card(int w,int h)
	{
		this.a=w;
		this.b=h;
		
	}
	public int compareTo(Card that)
	{
		return this.a-that.a;
	}
}
