Problem: The first crossword puzzle was published on December 21, 1913 by Arthur Wynne. To celebrate the centennial of his great-great-grandfather's invention, John "Coward" Wynne1 was struggling to make crossword puzzles. He was such a coward that whenever he thought of a tricky clue for a word, he couldn’t stop worrying if people would blame him for choosing a bad clue that could never mean that word. At the end of the day, he cowardly chose boring clues, which made his puzzles less interesting.

One day, he came up with a brilliant idea: puzzles in which word meanings do not matter, and yet interesting. He told his idea to his colleagues, who admitted that the idea was intriguing. They even named his puzzles "Coward's Crossword Puzzles" after his nickname.

However, making a Coward's crossword puzzle was not easy. Even though he did not have to think about word meanings, it was not easy to check if a puzzle has one and only one set of answers. As the day of the centennial anniversary was approaching, John started worrying if he would not be able to make interesting ones in time. Let's help John by writing a program that solves Coward's crossword puzzles.

Each puzzle consists of h × w cells along with h across clues and w down clues. The clues are regular expressions written in a pattern language whose BNF syntax is given as in the table below.


clue       ::= "^" pattern "$"
pattern    ::= simple | pattern "|" simple
simple     ::= basic | simple basic
basic      ::= elementary | elementary "*"
elementary ::= "." | "A" | "B" | ... | "Z" | "(" pattern ")"


Table J.1. BNF syntax of the pattern language.

The clues (as denoted by p and q below) match words (as denoted by s below) according to the following rules.

* ^p$ matches s if p matches s.
* p|q matches a string s if p and/or q matches s.
* pq matches a string s if there exist s1 and s2 such that s1s2 = s, p matches s1, and q matches s2.
* p* matches a string s if s is empty, or there exist s1 and s2 such that s1s2 = s, p matches
* s1, and p* matches s2.
* Each of A, B, . . . , Z matches the respective letter itself.
* (p) matches s if p matches s.
* . is the shorthand of (A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z).



Below is an example of a Coward’s crossword puzzle with the answers filled in the cells.

<image>



Java Specific: Submitted Java programs may not use classes in the java.util.regex package.
C++ Specific: Submitted C++ programs may not use the std::regex class.

Notes

1 All characters appearing in this problem, except for Arthur Wynne, are fictitious. Any resemblance to real persons, living or dead, is purely coincidental.



Input

The input consists of multiple datasets, each of which represents a puzzle given in the following format.


h w
p1
p2
...
ph
q1
q2
...
q2


Here, h and w represent the vertical and horizontal numbers of cells, respectively, where 2 ≤ h,w ≤ 4. The pi and qj are the across and down clues for the i-th row and j-th column, respectively. Any clue has no more than 512 characters.

The last dataset is followed by a line of two zeros. You may assume that there are no more than 30 datasets in the input.

Output

For each dataset, when the puzzle has a unique set of answers, output it as h lines of w characters. When the puzzle has no set of answers, or more than one set of answers, output "none" or "ambiguous" without double quotations, respectively.

Examples

Input

2 2
^(C|I|T|Y)*


Output

IC
PC
HE
LP
ALLY
OUNE
EDIS
LOVE
ambiguous
none
ARKA
NSAS


Input

2 2
^(C|I|T|Y)*$
^(C|O|P|S)*$
^(F|L|I|P)*$
^(B|A|C|K)*$
2 2
^HE|LL|O*$
^(P|L|E|A|S|E)*$
^(H|L)*$
^EP|IP|EF$
4 4
^LONG|TALL|S*ALLY$
^(R*EV*|OL*U(TIO)*N)*$
^(STRAWBERRY|F*I*E*L*D*S*|FOREVER)*$
^P.S.|I|LOVE|YOU$
^(RE|A|L)((L|OV*E)*)$
^(LUC*Y*|IN.THE.SKY)(WITH|DI*A*M*ON*D*S*)$
^(IVE*|GOT|A|F*E*E*L*I*N*G*)*$
^YEST*E*R*D*A*Y*$
2 3
^(C|P)(OL|AS)$
^(LU|TO)(X|R)$
^CT|PL$
^OU|AO$
^SR|LX$
2 2
^T*|(HI)|S*$
^SE|NT|EN|CE$
^IS$
^(F|A|L|S|E)*$
2 4
^ARKA|BARB|COLU$
^NSAS|ADOS|MBIA$
^..$
^..$
^KA|RO|LI$
^AS|BA|US$
0 0


Output

IC
PC
HE
LP
ALLY
OUNE
EDIS
LOVE
ambiguous
none
ARKA
NSAS

Solution (in CPP):

Solution:
// very kuso problem

#include <cassert>// c
#include <iostream>// io
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>// container
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#include <algorithm>// other
#include <complex>
#include <numeric>
#include <functional>
#include <random>
#include <regex>
using namespace std;
typedef long long ll;typedef unsigned long long ull;typedef long double ld;

#define ALL(c) c.begin(),c.end()
#define IN(l,v,r) (l<=v && v < r)
template<class T> void UNIQUE(T& v){
	sort(ALL(v));
	v.erase(unique(ALL(v)),v.end());
}

#define DUMP(x) cerr << #x <<" = " << (x)
#define LINE() cerr<< " (L" << __LINE__ << ")"

#define range(i,l,r) for(int i=(int)l;i<(int)(r);i++)
// struct range{
// 	struct Iter{
// 		int v,step;
// 		Iter& operator++(){v+=step;return *this;}
// 		bool operator!=(Iter& itr){return v<itr.v;}
// 		int& operator*(){return v;}
// 	};
// 	Iter i, n;
// 	range(int i, int n,int step):i({i,step}), n({n,step}){}
// 	range(int i, int n):range(i,n,1){}
// 	range(int n):range(0,n){}
// 	Iter& begin(){return i;}
// 	Iter& end(){return n;}
// };

//input
template<typename T1,typename T2> istream& operator >> (istream& is,pair<T1,T2>& p){return is>>p.first>>p.second;}
template<typename T1> istream& operator >> (istream& is,tuple<T1>& t){return is >> get<0>(t);}
template<typename T1,typename T2> istream& operator >> (istream& is,tuple<T1,T2>& t){return is >> get<0>(t) >> get<1>(t);}
template<typename T1,typename T2,typename T3> istream& operator >> (istream& is,tuple<T1,T2,T3>& t){return is >>get<0>(t)>>get<1>(t)>>get<2>(t);}
template<typename T1,typename T2,typename T3,typename T4> istream& operator >> (istream& is,tuple<T1,T2,T3,T4>& t){return is >> get<0>(t)>>get<1>(t)>>get<2>(t)>>get<3>(t);}
template<typename T> istream& operator >> (istream& is,vector<T>& as){range(i,0,as.size())is >>as[i];return is;}
//output
template<typename T> ostream& operator << (ostream& os, const set<T>& ss){for(auto a:ss){if(a!=ss.begin())os<<" "; os<<a;}return os;}
template<typename T1,typename T2> ostream& operator << (ostream& os, const pair<T1,T2>& p){return os<<p.first<<" "<<p.second;}
template<typename K,typename V> ostream& operator << (ostream& os, const map<K,V>& m){bool isF=true;for(auto& p:m){if(!isF)os<<endl;os<<p;isF=false;}return os;}
template<typename T1> ostream& operator << (ostream& os, const tuple<T1>& t){return os << get<0>(t);}
template<typename T1,typename T2> ostream& operator << (ostream& os, const tuple<T1,T2>& t){return os << get<0>(t)<<" "<<get<1>(t);}
template<typename T1,typename T2,typename T3> ostream& operator << (ostream& os, const tuple<T1,T2,T3>& t){return os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t);}
template<typename T1,typename T2,typename T3,typename T4> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4>& t){return os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t);}
template<typename T> ostream& operator << (ostream& os, const vector<T>& as){range(i,0,as.size()){if(i!=0)os<<" "; os<<as[i];}return os;}
template<typename T> ostream& operator << (ostream& os, const vector<vector<T>>& as){range(i,0,as.size()){if(i!=0)os<<endl; os<<as[i];}return os;}

struct Edge{
	char c;int f,t;
};

class NFA{
public:
	static NFA ONE;
	int N;
	vector<Edge> es;
	vector<vector<int>> f_cache, t_cache;

	int s,t;
	NFA(int N = 0):N(N),s(0),t(1){
		f_cache = t_cache = vector<vector<int>>(N);
	}
	void add_edge(char c,int f,int t){
		int eid = es.size();
		es.push_back({c,f,t});
		f_cache[f].push_back(eid);t_cache[t].push_back(eid);
	}
	static NFA disjoint(NFA& a,NFA& b){
		// merge technique
		NFA& res = (a.es.size() < b.es.size()? b : a), add = (a.es.size() < b.es.size()? a : b);
		
		res.f_cache.resize(res.N + add.N);res.t_cache.resize(res.N + add.N);
		int eid = res.es.size();
		for(Edge& e:add.es){
			e.f += res.N; e.t += res.N;
			res.es.push_back(e);
			res.f_cache[e.f].push_back(eid);res.t_cache[e.t].push_back(eid);eid++;
		}
		res.N += add.N;
		return res;
	}
	static NFA Union(NFA& a,NFA& b){
		bool bl = a.es.size() < b.es.size();
		int as = (bl?b.N:0)+a.s,at = (bl?b.N:0)+a.t,aN = a.N, bs = (!bl?a.N:0)+b.s,bt = (!bl?a.N:0)+b.t, bN = b.N;
		int S = aN+bN,T = aN+bN+1;
		NFA ab = disjoint(a,b),ab1 = disjoint(ab,ONE),res = disjoint(ab1,ONE);
		res.add_edge('-',S,as); res.add_edge('-',S,bs);res.add_edge('-',at,T); res.add_edge('-',bt,T);
		res.s = S; res.t = T;
		return res;
	}
	static NFA Concat(NFA& a,NFA& b){
		bool bl = a.es.size() < b.es.size();
		int as = (bl?b.N:0)+a.s,at = (bl?b.N:0)+a.t,aN = a.N, bs = (!bl?a.N:0)+b.s,bt = (!bl?a.N:0)+b.t, bN = b.N;
		NFA res = disjoint(a,b);
		res.add_edge('-',at,bs);
		res.s = as; res.t = bt;
		return res;
	}
	static NFA Star(NFA& a){
		NFA res = disjoint(a,ONE);
		res.add_edge('-',res.N-1,a.s);
		res.add_edge('-',a.t,res.N-1);
		res.s = res.t = res.N-1;
		return res;
	}

	// parsing 
	static NFA pattern(string& s,int& i,int e){
		NFA p = simple(s,i,e);
		while(i < e && s[i]=='|'){
			i++;// '|'
			NFA q = simple(s,i,e);
			p = NFA::Union(p,q);
		}
		return p;
	}
	static NFA simple(string& s,int& i,int e){
		NFA p = basic(s,i,e);
		while(i < e && s[i]!='|'){
			NFA q = basic(s,i,e);
			p = NFA::Concat(p,q);
		}
		return p;
	}
	static NFA basic(string& s,int& i,int e){
		NFA p = elementary(s,i,e);
		if(i < (int)s.size() && s[i]=='*'){
			i++;// *
			p = NFA::Star(p);
		}
		return p;
	}
	static NFA elementary(string& s,int& i,int e){
		NFA p;
		if(s[i]=='('){
			i++; // (
			int d=1;
			for(int j=i;j<e;j++){
				if(s[j]=='(') d++;
				if(s[j]==')') d--;
				if(d==0){
					e = j;break;
				}
			}
			p = pattern(s,i,e);
			i++; // )
		}else{
			p = NFA(2);
			p.add_edge(s[i],p.s,p.t);
			i++;// c
		}
		return p;
	}
} NFA::ONE = NFA(1);

int rc = 0;
class Main{
	public:

	int h,w;
	vector<string> tmp,res;

	vector<NFA> NFAs;
	vector<vector<int>> stats;
	vector<vector<vector<int>>> reachable;
	vector<vector<vector<vector<int>>>> trans;

	void create_reachable(int nind){
		NFA& nfa = NFAs[nind];
		queue<pair<int,int>> que; que.push({nfa.t,0});
		reachable[nind][nfa.t][0] = true;
		while(!que.empty()){
			int t,d;tie(t,d) = que.front();que.pop();
			//back
			for(int eid:nfa.t_cache[t]){
				Edge& e = nfa.es[eid];
				if(e.c=='-'){
					if(!reachable[nind][e.f][d]){
						reachable[nind][e.f][d] = true;
						que.push({e.f,d});
					}
				}else{
					if(d+1 <reachable[nind][e.f].size() && !reachable[nind][e.f][d+1]){
						reachable[nind][e.f][d+1] = true;
						que.push({e.f,d+1});
					}
				}
			}
		}
	}

	void create_trans(int nind,int st,char nc){
		NFA& nfa = NFAs[nind];

		vector<bool> passed(nfa.N);
		passed[st] = true;
		// eps trans
		{
			queue<int> que;
			range(i,0,passed.size())if(passed[i])que.push(i);
			while(!que.empty()){
				int s = que.front();que.pop();
				for(int eid : nfa.f_cache[s])if(nfa.es[eid].c =='-' && !passed[nfa.es[eid].t]){
					passed[nfa.es[eid].t] = true;
					que.push(nfa.es[eid].t);
				}
			}
		}
		// trans
		{
			vector<bool> npassed(nfa.N);
			range(s,0,nfa.N)if(passed[s]) for(int eid : nfa.f_cache[s]){
				char c = nfa.es[eid].c;
				int t = nfa.es[eid].t;
				if(nc==c || c=='.') npassed[t] = true;
			}
			passed = npassed;
		}

		// eps trans
		{
			queue<int> que;
			range(i,0,passed.size())if(passed[i])que.push(i);
			while(!que.empty()){
				int s = que.front();que.pop();
				for(int eid : nfa.f_cache[s])if(nfa.es[eid].c =='-' && !passed[nfa.es[eid].t]){
					passed[nfa.es[eid].t] = true;
					que.push(nfa.es[eid].t);
				}
			}
		}

		range(s,0,passed.size())if(passed[s]){
			bool exeps = false, alleps = true;
			for(int eid : nfa.f_cache[s]){
				exeps |= nfa.es[eid].c=='-';
				alleps &= nfa.es[eid].c=='-';
			}
			// ?? ????§???????????????´?????????????????? for ?????????
			if(exeps && alleps && nfa.t != s)continue; 
			trans[nind][st][nc-'A'].push_back(s);
		}
	}

	void dfs(int y,int x,int c){
		// cerr << y <<" " << x <<endl;
		// cerr << tmp <<endl;

		if(rc>1)return;
		if(y==h){
			rc+=c;
			res = tmp;
			return;
		}

		// ????????????????????¶??????????????´????????????????????????????????¢?´¢
		vector<vector<int>> ynstats(26),xnstats(26);
		for(char nc = 'A';nc <= 'Z'; nc++){
			for(int s:stats[y])for(int t:trans[y][s][nc-'A'])ynstats[nc-'A'].push_back(t);
			UNIQUE(ynstats[nc-'A']);
		}
		for(char nc = 'A';nc <= 'Z'; nc++){
			for(int s:stats[h+x])for(int t:trans[h+x][s][nc-'A'])xnstats[nc-'A'].push_back(t);
			UNIQUE(xnstats[nc-'A']);
		}
		vector<int> gid(26);iota(ALL(gid),0);
		for(char c1='A'; c1 <= 'Z';c1++){
			for(char c2='A'; c2 < c1;c2++)if(gid[c2-'A']==c2-'A'){
				if(ynstats[c1-'A'].size() == ynstats[c2-'A'].size() && xnstats[c1-'A'].size() == xnstats[c2-'A'].size()){
					bool eq = true;
					range(i,0,ynstats[c1-'A'].size())eq &= ynstats[c1-'A'][i] == ynstats[c2-'A'][i];
					range(i,0,xnstats[c1-'A'].size())eq &= xnstats[c1-'A'][i] == xnstats[c2-'A'][i];
					if(eq){
						gid[c1-'A']=gid[c2-'A'];
						break;
					}
				}
			}
		}
		vector<int> gc(26);
		range(i,0,26)gc[gid[i]]++;

		for(char c='A'; c <= 'Z';c++)if(gid[c-'A']==c-'A'){
			tmp[y][x] = c;
			bool tmpOK = true;
			// eda ??????????????? de ikerukana ?
			{
				bool ok = false;
				for(int s:ynstats[c-'A'])ok |= reachable[y][s][w-1-x];
				tmpOK &= ok;
			}
			{
				bool ok = false;
				for(int s:xnstats[c-'A'])ok |= reachable[h+x][s][h-1-y];
				tmpOK &= ok;
			}
			if(x == w-1){
				bool ok = false;
				for(int s:ynstats[c-'A'])ok |= s == NFAs[y].t;
				tmpOK &= ok;
			}
			if(y == h-1){
				bool ok = false;
				for(int s:xnstats[c-'A'])ok |= s == NFAs[h+x].t;
				tmpOK &= ok;
			}
			if(tmpOK){
				vector<int> tmpp = stats[y],tmpq = stats[h+x];
				stats[y] = ynstats[c-'A']; stats[h+x] = xnstats[c-'A'];
				if(x+1 < w) dfs(y,x+1,gc[c-'A']);
				else dfs(y+1,0,gc[c-'A']);
				stats[y] = tmpp; stats[h + x] = tmpq;
			}
		}
	}

	void run(){
		while(true){
			cin >> h >> w;
			if(h==0 && w==0)break;
			rc = 0;
			tmp = res = vector<string>(h,string(w,'-'));
			vector<string> ss(h+w);cin >> ss;
 			// h <= 4, w <= 4
			NFAs = vector<NFA>(h+w);
			range(i,0,h+w){
				string s = "";
				range(j,1,ss[i].size()-1)s+=ss[i][j];
				int cur = 0, e = s.size();
				NFAs[i]= NFA::pattern(s,cur,e);
			}
			stats = vector<vector<int>>(h+w);
			range(i,0,h+w) stats[i].push_back(NFAs[i].s);

			reachable = vector<vector<vector<int>>>(h+w);
			range(i,0,h){
				reachable[i] = vector<vector<int>>(NFAs[i].N);
				range(s,0,NFAs[i].N) reachable[i][s] = vector<int>(h+1);
			}
			range(i,0,w){
				reachable[h+i] = vector<vector<int>>(NFAs[h+i].N);
				range(s,0,NFAs[h+i].N) reachable[h+i][s] = vector<int>(w+1);
			}
			range(i,0,h+w) create_reachable(i);
			
			trans = vector<vector<vector<vector<int>>>>(h+w);
			range(i,0,h+w){
				trans[i] = vector<vector<vector<int>>>(NFAs[i].N,vector<vector<int>>(26));
				range(s,0,NFAs[i].N)range(c,'A','Z'+1)create_trans(i,s,c);
			}

			// cerr << NFAs[0].t <<endl;
			// range(i,0,NFAs[0].es.size()){
			// 	cerr << NFAs[0].es[i].c <<" " <<NFAs[0].es[i].f <<" " <<NFAs[0].es[i].t <<endl;
			// }
			// cerr << NFAs[0].t_cache <<endl;

			dfs(0,0,1);
			if(rc > 1){
				cout << "ambiguous" <<endl; 
			}else if(rc == 0){
				cout << "none" <<endl;
			}else{
				range(i,0,h) cout << res[i] <<endl;
			}
		}
	}
};

int main(){
	cout <<fixed<<setprecision(20);
	cin.tie(0);
	ios::sync_with_stdio(false);
	Main().run();
	return 0;
}