Problem:
Problem Statement
One day in a forest, Alice found an old monolith.
She investigated the monolith, and found this  was a sentence written in an old language.
A sentence consists of glyphs and rectangles which surrounds them.
For the above example, there are following glyphs.
Notice that some glyphs are flipped horizontally in a sentence.
She decided to transliterate it using ASCII letters assigning an alphabet to each glyph, and
[
and
]
to rectangles.
If a sentence contains a flipped glyph,  she transliterates it from right to left.
For example,  she could assign
a
and
b
to the above glyphs respectively.
Then the above sentence  would be transliterated into
[[ab][ab]a]
.
After examining the sentence, Alice figured out that the sentence was organized by the following structure:
A sentence <seq> is a sequence consists of  zero or more <term>s.
A term <term> is either a glyph or a <box>. A glyph may be flipped.
<box> is a rectangle surrounding a <seq>. The height of a box is larger than any glyphs inside.
Now, the sentence written on the monolith is a nonempty <seq>.
Each term in the sequence fits in a rectangular bounding box, although the boxes are not explicitly indicated for glyphs.  Those bounding boxes for adjacent terms have no overlap to each other.
Alice  formalized the transliteration rules as follows.
Let
f
be the transliterate function.
Each sequence
s = t_1 t_2 ... t_m
is written either from left to right, or from right to left.
However, please note here
t_1
corresponds to the leftmost term in the sentence,
t_2
to the 2nd term from the left, and so on.
Let's define
ḡ
to be the flipped glyph
g
.
A sequence must have been written from right to left, when a sequence contains one or more single-glyph term which is unreadable without flipping, i.e. there exists an integer
i
where
t_i
is a single glyph
g
, and
g
is not in the glyph dictionary given separately whereas
ḡ
is.
In such cases
f(s)
is defined to be
f(t_m) f(t_{m-1}) ... f(t_1)
, otherwise
f(s) = f(t_1) f(t_2) ... f(t_m)
.
It is guaranteed that all the glyphs in the sequence are flipped if there is one or more glyph which is unreadable without flipping.
If the term
t_i
is a box enclosing a sequence
s'
,
f(t_i) =
[
f(s')
]
.
If the term
t_i
is a glyph
g
,
f(t_i)
is mapped to an alphabet letter corresponding to the glyph
g
, or
ḡ
if the sequence containing
g
is written from right to left.
Please make a program to transliterate the sentences on the monoliths to help Alice.
Input
The input consists of several  datasets.
The end of the input is denoted by two zeros separated by a single-space.
Each  dataset  has the following format.
n
m
glyph_1
...
glyph_n
string_1
...
string_m
n
(
1\leq n\leq 26
) is the number of glyphs and
m
(
1\leq m\leq 10
) is the number of monoliths.
glyph_i
is given by the following format.
c
h
w
b_{11}
...
b_{1w}
...
b_{h1}
...
b_{hw}
c
is a lower-case alphabet that Alice assigned to the glyph.
h
and
w
(
1 \leq h \leq 15
,
1 \leq w \leq 15
)  specify the height 
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> HA;
const int N = 105, M = 1005, MOD1 = 1e9 + 7, MOD2 = 1e9 + 9;
char s[N][M];
HA calc_HA(int x1, int y1, int x2, int y2) {
	int a1 = 0, a2 = 0;
	for (int i = x1; i <= x2; ++ i) {
		for (int j = y1; j <= y2; ++ j) {
			a1 = (a1 * 31LL + (s[i][j] == '*')) % MOD1;
			a2 = (a2 * 17LL + (s[i][j] == '*')) % MOD2;
		}
	}
	return make_pair(a1, a2);
}
HA calc_RHA(int x1, int y1, int x2, int y2) {
	int a1 = 0, a2 = 0;
	for (int i = x1; i <= x2; ++ i) {
		for (int j = y2; j >= y1; -- j) {
			a1 = (a1 * 31LL + (s[i][j] == '*')) % MOD1;
			a2 = (a2 * 17LL + (s[i][j] == '*')) % MOD2;
		}
	}
	return make_pair(a1, a2);
}
int cnt[N][M];
map<HA, string> ch;
int blank(int x1, int y1, int x2, int y2) {
	return cnt[x2][y2] - cnt[x1 - 1][y2] - cnt[x2][y1 - 1] + cnt[x1 - 1][y1 - 1];
}
int rev[26];
pair<string, bool> dfs(int x1, int y1, int x2, int y2) {
	if (x1 > x2 || y1 > y2 || !blank(x1, y1, x2, y2)) return make_pair("", 0);
	while (!blank(x1, y1, x1, y2)) x1 ++;
	while (!blank(x2, y1, x2, y2)) x2 --;
	while (!blank(x1, y1, x2, y1)) y1 ++;
	while (!blank(x1, y2, x2, y2)) y2 --;
	if (y2 - y1 + 1 <= 15 && x2 - x1 + 1 <= 15) {
		auto ha = calc_HA(x1, y1, x2, y2);
		if (ch.count(ha)) return make_pair(ch[ha], 0);
		ha = calc_RHA(x1, y1, x2, y2);
		if (ch.count(ha)) return make_pair(ch[ha], 1);
	}
	if (blank(x1, y1, x1, y2) + blank(x2, y1, x2, y2) + blank(x1 + 1, y1, x2 - 1, y1) + blank(x1 + 1, y2, x2 - 1, y2) == 2 * (x2 - x1 + y2 - y1)) {
		x1 ++; y1 ++;
		x2 --; y2 --;
		int las = y1;
		vector<string> all;
		bool flip = 0;
		for (int i = y1 + 1; i <= y2; ++ i) {
			if (!blank(x1, i, x2, i)) {
				auto a = dfs(x1, las + 1, x2, i - 1);
				all.push_back(a.first);
				flip = flip || a.second;
				las = i;
			}
		}
		if (flip) {
			reverse(all.begin(), all.end());
			for (string &a : all) if ((int) a.length() == 1 && rev[a[0] - 'a'] != -1) a[0] = rev[a[0] - 'a'] + 'a';
		}
		string tmp = "[";
		for (string &a : all) tmp += a;
		tmp += ']';
		return make_pair(tmp, 0);
	}
	else {
		int las = y1 - 1;
		vector<string> all;
		bool flip = 0;
		for (int i = y1 + 1; i <= y2 + 1; ++ i) {
			if (!blank(x1, i, x2, i) || i > y2) {
				auto a = dfs(x1, las + 1, x2, i - 1);
				all.push_back(a.first);
				flip = flip || a.second;
				las = i;
			}
		}
		if (flip) {
			reverse(all.begin(), all.end());
			for (string &a : all) if ((int) a.length() == 1 && rev[a[0] - 'a'] != -1) a[0] = rev[a[0] - 'a'] + 'a';
		}
		string tmp = "";
		for (string &a : all) tmp += a;
		return make_pair(tmp, 0);
	}
}
int main() {
	int n, m;
	while (scanf("%d%d", &n, &m) == 2) {
		if (n + m == 0) break;
		ch.clear();
		memset(rev, -1, sizeof(rev));
		for (int i = 0; i < n; ++ i) {
			int h, w;
			char c[3];
			scanf("%s%d%d", c, &h, &w);
			for (int j = 1; j <= h; ++ j) scanf("%s", s[j] + 1);
			string tmp;
			tmp += c[0];
			auto r = calc_RHA(1, 1, h, w);
			if (ch.count(r)) {
				rev[ch[r][0] - 'a'] = c[0] - 'a';
				rev[c[0] - 'a'] = ch[r][0] - 'a';
			}
			ch[calc_HA(1, 1, h, w)] = tmp;
		}
		for (int i = 0; i < m; ++ i) {
			int h, w;
			scanf("%d%d", &h, &w);
			for (int j = 1; j <= h; ++ j) scanf("%s", s[j] + 1);
			for (int x = 1; x <= h; ++ x) {
				for (int y = 1; y <= w; ++ y) cnt[x][y] = cnt[x - 1][y] + cnt[x][y - 1] - cnt[x - 1][y - 1] + (s[x][y] == '*');
			}
			string ans = dfs(1, 1, h, w).first;
			cout << ans << endl;
		}
		puts("#");
	}
}
accuracy: 1
time_ms: 30
memory_kb: 3984
final_rank: 5

code_snippet: // AOJ #2540 Ancient Commemorative Monolith
// 2025.3.18

#include <bits/stdc++.h>
using namespace std;

string img[128];
int nrow[128][1024];
int ncol[1024][128];
int maxGlyphHeight;

struct Glyph {
    char id;
    vector<string> pattern;
    vector<string> reversedPattern;

    void input() {
        int height, width;
        cin >> id >> height >> width;
        pattern.resize(height);
        reversedPattern.resize(height);
        for (int i = 0; i < height; ++i) {
            cin >> pattern[i];
            reversedPattern[i] = string(pattern[i].rbegin(), pattern[i].rend());
        }
        maxGlyphHeight = max(maxGlyphHeight, height);
    }

    bool matchPattern(int startY, int startX, int endY, int endX, const vector<string> &targetPattern) const {
        int targetHeight = targetPattern.size();
        int targetWidth = targetPattern[0].size();
        if (endY - startY + 1 != targetHeight || endX - startX + 1 != targetWidth) {
            return false;
        }
        for (int i = 0; i < targetHeight; ++i) {
            if (img[startY + i].substr(startX, targetWidth) != targetPattern[i]) {
                return false;
            }
        }
        return true;
    }

    bool match(int startY, int startX, int endY, int endX) const {
        return matchPattern(startY, startX, endY, endX, pattern);
    }

    bool matchReversed(int startY, int startX, int endY, int endX) const {
        return matchPattern(startY, startX, endY, endX, reversedPattern);
    }
};

vector<Glyph> glyphs;

string term(int y1, int x1, int y2, int x2);

string seq(int startY, int startX, int endY, int endX) {
    bool encounteredStarColumn = false;
    vector<string> subTerms;

    for (int col = startX; col <= endX + 1; ++col) {
        if (col <= endX && (ncol[col][endY] - ncol[col][startY - 1] > 0)) {
            encounteredStarColumn = true;
        }
        else if (encounteredStarColumn) {
            encounteredStarColumn = false;
            subTerms.push_back(term(startY, startX, endY, col - 1));
            startX = col + 1;
        }
    }

    int indexOffset = 1;
    for (size_t i = 0; i < subTerms.size(); ++i) {
        if (subTerms[i][0] == '_' && subTerms[i][1] == '_') {
            indexOffset = 2;
            break;
        }
    }
    for (size_t i = 0; i < subTerms.size(); ++i) {
        if (subTerms[i][0] == '_') subTerms[i] = string(1, subTerms[i][indexOffset]);
    }
    if (indexOffset == 1) return accumulate(subTerms.begin(), subTerms.end(), string());
    return accumulate(subTerms.rbegin(), subTerms.rend(), string());
}

string term(int startY, int startX, int endY, int endX) {
    while (nrow[startY][endX] - nrow[startY][startX - 1] == 0) ++startY;
    while (nrow[endY][endX] - nrow[endY][startX - 1] == 0) --endY;
    while (ncol[startX][endY] - ncol[startX][startY - 1] == 0) ++startX;
    while (ncol[endX][endY] - ncol[endX][startY - 1] == 0) --endX;

    string ans;
    if (endY - startY + 1 > maxGlyphHeight) ans = '[' + seq(startY + 2, startX + 2, endY - 2, endX - 2) + ']';
    else {
        ans = "___";
        for (size_t i = 0; i < glyphs.size(); ++i) {
            if (glyphs[i].match(startY, startX, endY, endX)) {
                ans[1] = glyphs[i].id;
                break;
            }
        }
        for (size_t i = 0; i < glyphs.size(); ++i) {
            if (glyphs[i].matchReversed(startY, startX, endY, endX)) {
                ans[2] = glyphs[i].id;
                break;
            }
        }
    }
    return ans;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    while (true) {
        int N, M;
        string ins;

        cin >> N >> M;
        if (N == 0) break;

        maxGlyphHeight = 0;
        glyphs.resize(N);
        for (int i = 0; i < N; ++i) {
            glyphs[i].input();
        }
        for (int k = 1; k <= M; ++k) {
            int height, width;
            cin >> height >> width;
            img[0].assign(width + 1, '.');
            for (int i = 1; i <= height; ++i) {
                cin >> ins;
                img[i] = '.' + ins;
                for (int j = 1; j <= width; ++j) {
                    nrow[i][j] = nrow[i][j - 1] + (img[i][j] == '*');
                    ncol[j][i] = ncol[j][i - 1] + (img[i][j] == '*');
                }
            }
            ins = seq(1, 1, height, width);
            cout << ins << endl;
        }
        cout << '#' << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 4668
final_rank: 6

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


struct Info{

	int h,w;
	char ch,rev_ch;
	char table[15][16],rev_table[15][16];
};

struct Data{

	string str;
	bool is_rev;
};

struct State{
	State(){
		row = col = 0;
	}

	State(int arg_row,int arg_col){
		row = arg_row;
		col = arg_col;
	}
	int row,col;
};

int num_glyph,num_monolith;
int max_glyph_H;
int index_table[26];
Info info[26];
char base_map[105][1010];

Data calc_term(int,int,int,int);
string calc_seq(int,int,int,int);
string calc_box(int,int,int,int);


bool is_Same(char A[15][16],char B[15][16],int H,int W){

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			if(A[row][col] != B[row][col]){

				return false;
			}
		}
	}

	return true;
}

//最大のグリフより高いならBOX
bool is_BOX(int row,int col){

	int tmp_H = 1;

	while(base_map[row+1][col] == '*'){

		row++;
		tmp_H++;
	}

	return tmp_H > max_glyph_H;
}


Data calc_term(int row1,int col1,int row2,int col2){

	Data ret;
	ret.str = "";
	ret.is_rev = false;


	char work[15][16];

	for(int row = row1; row <= row2; row++){
		for(int col = col1; col <= col2; col++){

			work[row-row1][col-col1] = base_map[row][col];
		}
	}

	int H = row2-row1+1,W = col2-col1+1;

	bool FLG = false;

	//★★先に、ノーマル全部を探す★★
	for(int i = 0; i < num_glyph; i++){

		if(info[i].h != H || info[i].w != W)continue;

		if(is_Same(work,info[i].table,H,W)){
			FLG = true;
			ret.str = info[i].ch;
			break;
		}
	}

	if(!FLG){

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


			if(info[i].h != H || info[i].w != W)continue;

			if(is_Same(work,info[i].rev_table,H,W)){

				ret.str = info[i].ch;
				ret.is_rev = true;
				break;
			}
		}
	}

	return ret;
}

string calc_seq(int row1,int col1,int row2,int col2){

	string ret = "";
	bool rev_FLG = false;
	vector<string> V;

	for(int row = row1,col = col1; col <= col2; ){

		if(base_map[row][col] == '*'){ //BOX or term発見

			if(is_BOX(row,col)){

				int tmp_row,tmp_col;

				for(tmp_col = col; tmp_col+1 <= col2 && base_map[row][tmp_col+1] == '*'; tmp_col++);
				for(tmp_row = row; tmp_row+1 <= row2 && base_map[tmp_row+1][col] == '*'; tmp_row++);

				V.push_back(calc_box(row,col,tmp_row,tmp_col));

				row = row1;
				col = tmp_col+1;

			}else{

				//上下左右の座標を求める
				int top = row,under = row,left = col,right = col;
				bool black_FLG;

				int tmp_row,tmp_col;

				for(tmp_row = row+1; tmp_row <= row2; tmp_row++){
					if(base_map[tmp_row][col] == '*'){
						under = tmp_row;
					}
				}

				for(tmp_col = col+1; tmp_col <= col2; tmp_col++){
					black_FLG = false;
					for(tmp_row = row1; tmp_row <= row2;tmp_row++){
						if(base_map[tmp_row][tmp_col] == '*'){
							top = min(top,tmp_row);
							under = max(under,tmp_row);
							right = tmp_col;
							black_FLG = true;
						}

					}
					if(!black_FLG)break;
				}

				Data term = calc_term(top,left,under,right);

				V.push_back(term.str);
				rev_FLG |= term.is_rev;

				col = right+1;
				row = row1;
			}

		}else{

			row++;
			if(row > row2){
				row = row1;
				col++;
			}
		}
	}

	if(rev_FLG){

		reverse(V.begin(),V.end());
		for(int i = 0; i < V.size(); i++){
			if(V[i].length() >= 2)continue; //箱はカッコが必ずついている

			int tmp_index = index_table[V[i][0]-'a'];
			char rev_ch = info[tmp_index].rev_ch;
			if(rev_ch == '@')continue;

			V[i][0] = rev_ch; //元の文字に戻す
		}
	}

	for(int i = 0; i < V.size(); i++){

		ret += V[i];
	}

	return ret;
}

string calc_box(int row1,int col1,int row2,int col2){

	string ret = calc_seq(row1+1,col1+1,row2-1,col2-1);
	ret = "[" + ret + "]";

	return ret;
}


void func(){

	char buf[2];

	max_glyph_H = 0; //★★ボックスかどうか判定するのに、最大のグリフの高さが必要★★

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

		scanf("%s %d %d",buf,&info[i].h,&info[i].w);
		info[i].ch = buf[0];

		index_table[info[i].ch-'a'] = i; //文字からインデックスの逆引き表

		max_glyph_H = max(max_glyph_H,info[i].h);

		for(int row = 0; row < info[i].h; row++){

			scanf("%s",info[i].table[row]);
		}
		//左右反転したグリフを作る
		for(int col = 0; col < info[i].w; col++){
			for(int row = 0; row < info[i].h; row++){

				info[i].rev_table[row][col] = info[i].table[row][info[i].w-1-col];
			}
		}
	}


	//★★反転関係を調べる★★
	for(int i = 0; i < num_glyph; i++){

		char rev_ch = '@';

		for(int k = 0; k < num_glyph; k++){
			if(info[i].h != info[k].h || info[i].w != info[k].w)continue;

			if(is_Same(info[i].rev_table,info[k].table,info[i].h,info[i].w)){

				rev_ch = info[k].ch;
				break;
			}
		}

		info[i].rev_ch = rev_ch;
	}

	char work_map[1010];

	for(int loop = 0; loop < num_monolith; loop++){

		int H,W;
		scanf("%d %d",&H,&W);

		//ダミーセルで覆う
		for(int row = 0; row <= H+1; row++){
			base_map[row][0] = '.';
			base_map[row][W+1] = '.';
		}

		for(int col = 0; col <= W+1; col++){
			base_map[0][col] = '.';
			base_map[H+1][col] = '.';
		}

		for(int row = 1; row <= H; row++){

			scanf("%s",work_map);
			for(int col = 0;col < W; col++){
				base_map[row][col+1] = work_map[col];
			}
		}

		string ans;

		ans = calc_seq(0,0,H+1,W+1);

		printf("%s\n",ans.c_str());
	}
	printf("#\n");
}

int main(){

	while(true){

		scanf("%d %d",&num_glyph,&num_monolith);
		if(num_glyph == 0 && num_monolith == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3384
final_rank: 4

code_snippet: #include <bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep1(i,n) for(int i=1;i<=(int)(n);i++)
#define all(c) c.begin(),c.end()
#define pb push_back
#define fs first
#define sc second
#define show(x) cout << #x << " = " << x << endl
#define chmin(x,y) x=min(x,y)
#define chmax(x,y) x=max(x,y)
using namespace std;
typedef pair<int,int> P;
int N,M;
char c[26];
int h[26],w[26];
int flipto[26];
string bs[26][15];
vector<P> g[52];
int mxh;
int H,W;
string s[100];
bool isbox(int x,int y){
	int t=x;
	while(t<H&&s[t][y]=='*') t++;
	return t-x>mxh;
}
string seq(int u,int l,int d,int r){
	vector<string> ret;
	bool flip=0;
	int y=l,x=u;
	while(y<r){
		if(s[x][y]=='*'){
			if(isbox(x,y)){
				int nu=x+1,nl=y+1;
				int nd=nu,nr=nl;
				while(nd<H&&s[nd][y]=='*') nd++;
				while(nr<W&&s[x][nr]=='*') nr++;
				nd--,nr--;
				ret.pb(seq(nu,nl,nd,nr));
				x=u,y=nr+1;
				continue;
			}else{
				vector<P> vc;
				int L=y,U=1e5;
				for(;y<r;y++){
					bool iscol=0;
					for(x=u;x<d;x++){
						if(s[x][y]=='*') vc.pb(P(x,y)),iscol=1,chmin(U,x);
					}
					if(!iscol) break;
				}
				for(P& p:vc) p=P(p.fs-U,p.sc-L);
				sort(all(vc));
				rep(i,2*N){
					if(vc==g[i]){
						ret.pb(string(1,c[i%N]));
						if(i>=N) flip=1;
						break;
					}
				}
				x=u;
				continue;
			}
		}
		x++;
		if(x==d){
			y++;
			x=u;
		}
	}
	if(flip){
		reverse(all(ret));
		for(string& str:ret) if(str.size()==1){
			int tmp=flipto[str[0]-'a'];
			if(tmp>=0) str[0]=tmp+'a';
		}
	}
	string st="[";
	for(string str:ret) st+=str;
	st+="]";
	return st;
}
int main(){
	while(true){
		cin>>N>>M;
		if(N==0) break;
		rep(i,N*2) g[i].clear();
		mxh=0;
		rep(i,N){
			cin>>c[i]>>h[i]>>w[i];
			chmax(mxh,h[i]);
			rep(j,h[i]) cin>>bs[i][j];
			rep(j,h[i]) rep(k,w[i]) if(bs[i][j][k]=='*') g[i].pb(P(j,k)),g[i+N].pb(P(j,w[i]-1-k));
		}
		rep(i,2*N) sort(all(g[i]));
		rep(i,N) flipto[i]=-1;
		rep(i,N) rep(j,N) if(g[i+N]==g[j]) flipto[c[i]-'a']=c[j]-'a';
		rep(tt,M){
			cin>>H>>W;
			rep(i,H) cin>>s[i];
			string ans=seq(0,0,H,W);
			cout<<ans.substr(1,ans.size()-2)<<endl;
		}
		puts("#");
	}
}
accuracy: 1
time_ms: 190
memory_kb: 3332
final_rank: 7

code_snippet: #include<stdio.h>
#include<algorithm>
#include<string>
using namespace std;
typedef unsigned long long wolf;
wolf mod=1000000007;
char gly[26][20][20];
wolf Hash[26];
wolf revHash[26];
int gh[26];
int gw[26];
char in[2];
char str[110][1100];
pair<int,int> shrink(int top,int bottom,int left,int right){
	while(top<bottom){
		bool has=false;
		for(int i=left;i<right;i++)if(str[top][i]!='.'){has=true;break;}
		if(has)break;
		top++;
	}
	while(top<bottom){
		bool has=false;
		for(int i=left;i<right;i++)if(str[bottom-1][i]!='.'){has=true;break;}
		if(has)break;
		bottom--;
	}
	return make_pair(top,bottom);
}
pair<int,int> check(int top,int bottom,int left,int right){
	int H=bottom-top;
	int W=right-left;
	if(H>15||W>15){
		return make_pair(-1,-1);
	}
	wolf key=0;
	for(int i=0;i<H;i++)for(int j=0;j<W;j++){
		key*=mod;
		if(str[top+i][left+j]=='*')key++;
	}
	pair<int,int>ret=make_pair(-1,-1);
	for(int i=0;i<26;i++){
		if(gh[i]!=H||gw[i]!=W)continue;
		if(Hash[i]==key){
			bool ok=true;
			for(int j=0;j<H;j++)for(int k=0;k<W;k++)if(str[top+j][left+k]!=gly[i][j][k])ok=false;
			if(ok)ret.first=i;
		}
		if(revHash[i]==key){
			bool ok=true;
			for(int j=0;j<H;j++)for(int k=0;k<W;k++)if(str[top+j][left+k]!=gly[i][j][W-1-k])ok=false;
			if(ok)ret.second=i;
		}
	}
//	printf("%d %d %d %d: %d %d\n",top,bottom,left,right,ret.first,ret.second);
	return ret;
}
string solve(int top,int bottom,int left,int right){
	while(top<bottom){
		bool has=false;
		for(int i=left;i<right;i++)if(str[top][i]!='.'){has=true;break;}
		if(has)break;
		top++;
	}
	while(top<bottom){
		bool has=false;
		for(int i=left;i<right;i++)if(str[bottom-1][i]!='.'){has=true;break;}
		if(has)break;
		bottom--;
	}
	if(top==bottom)return "";
	int st=-1;
	string ltr="";bool LTR=true;
	string rtl="";bool RTL=true;
	for(int i=left;i<=right;i++){
		bool has=false;
		if(i<right){
			for(int j=top;j<bottom;j++){
				if(str[j][i]!='.')has=true;
			}
		}
		if(has){
			if(st==-1)st=i;
		}else{
			if(st!=-1){
				pair<int,int>hor=shrink(top,bottom,st,i);
				pair<int,int>val=check(hor.first,hor.second,st,i);
				if(val.first==-1&&val.second==-1){
					string tmp=solve(hor.first+1,hor.second-1,st+1,i-1);
					ltr=ltr+"["+tmp+"]";
					reverse(tmp.begin(),tmp.end());
					rtl=rtl+"]"+tmp+"[";
				}else{
					if(~val.first){
						ltr+=('a'+val.first);
					}else LTR=false;
					if(~val.second){
						rtl+=('a'+val.second);
					}else RTL=false;
				}
				st=-1;
			}
		}
	}
	if(LTR)return ltr;
	else{
		reverse(rtl.begin(),rtl.end());
		return rtl;
	}
}
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<26;i++)gh[i]=gw[i]=-1;
		for(int i=0;i<a;i++){
			int h,w;
			scanf("%s%d%d",in,&h,&w);
			int t=in[0]-'a';
			gh[t]=h;gw[t]=w;
			for(int j=0;j<h;j++)scanf("%s",gly[t][j]);
			Hash[t]=revHash[t]=0;
			for(int j=0;j<h;j++){
				for(int k=0;k<w;k++){
					Hash[t]*=mod;
					if(gly[t][j][k]=='*')Hash[t]++;
				}
				for(int k=w-1;k>=0;k--){
					revHash[t]*=mod;
					if(gly[t][j][k]=='*')revHash[t]++;
				}
			}
		}
		for(int i=0;i<b;i++){
			int h,w;
			scanf("%d%d",&h,&w);
			for(int j=0;j<h;j++)scanf("%s",str[j]);
			string ret=solve(0,h,0,w);
			printf("%s\n",ret.c_str());
		}
		printf("#\n");
	}
}
accuracy: 1
time_ms: 40
memory_kb: 1188
final_rank: 1

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;

string b[128];
int cr[128][1024], cc[1024][128];
int mh;

struct glyph{
	char c;
	vector<string> v, r;
	void input(){
		int h, w;
		cin >> c >> h >> w;
		v.resize(h);
		r.resize(h);
		for(int i = 0; i < h; ++i){
			cin >> v[i];
			r[i] = string(v[i].rbegin(), v[i].rend());
		}
		mh = max(mh, h);
	}
	bool match_base(int y1, int x1, int y2, int x2, const vector<string> &a) const{
		int h = a.size(), w = a[0].size();
		if(y2 - y1 + 1 != h || x2 - x1 + 1 != w){ return false; }
		for(int i = 0; i < h; ++i){
			if(b[y1 + i].compare(x1, w, a[i])){ return false; }
		}
		return true;
	}
	bool match(int y1, int x1, int y2, int x2) const{
		return match_base(y1, x1, y2, x2, v);
	}
	bool rmatch(int y1, int x1, int y2, int x2) const{
		return match_base(y1, x1, y2, x2, r);
	}
};

vector<glyph> gs;

string term(int, int, int, int);

string seq(int y1, int x1, int y2, int x2){
	bool ex = false;
	vector<string> v;
	for(int j = x1; j <= x2 + 1; ++j){
		if(j <= x2 && cc[j][y2] - cc[j][y1 - 1]){
			ex = true;
		}
		else if(ex){
			ex = false;
			v.push_back(term(y1, x1, y2, j - 1));
			x1 = j + 1;
		}
	}

	int idx = 1;
	for(size_t i = 0; i < v.size(); ++i){
		if(v[i][0] == '_' && v[i][1] == '_'){
			idx = 2;
			break;
		}
	}
	for(size_t i = 0; i < v.size(); ++i){
		if(v[i][0] == '_'){
			v[i] = string(1, v[i][idx]);
		}
	}

	if(idx == 1){
		return accumulate(v.begin(), v.end(), string());
	}
	return accumulate(v.rbegin(), v.rend(), string());
}

string term(int y1, int x1, int y2, int x2){
	while(cr[y1][x2] - cr[y1][x1 - 1] == 0){ ++y1; }
	while(cr[y2][x2] - cr[y2][x1 - 1] == 0){ --y2; }
	while(cc[x1][y2] - cc[x1][y1 - 1] == 0){ ++x1; }
	while(cc[x2][y2] - cc[x2][y1 - 1] == 0){ --x2; }

	string ret;
	if(y2 - y1 + 1 > mh){
		ret = '[' + seq(y1 + 2, x1 + 2, y2 - 2, x2 - 2) + ']';
	}
	else{
		ret = "___";
		for(size_t i = 0; i < gs.size(); ++i){
			if(gs[i].match(y1, x1, y2, x2)){
				ret[1] = gs[i].c;
				break;
			}
		}
		for(size_t i = 0; i < gs.size(); ++i){
			if(gs[i].rmatch(y1, x1, y2, x2)){
				ret[2] = gs[i].c;
				break;
			}
		}
	}
	return ret;
}

int main(){
	ios::sync_with_stdio(false);

	int n, m;
	string s;
	while(cin >> n >> m, n){
		mh = 0;
		gs.resize(n);
		for(int i = 0; i < n; ++i){
			gs[i].input();
		}
		for(int k = 1; k <= m; ++k){
			int h, w;
			cin >> h >> w;
			b[0].assign(w + 1, '.');
			for(int i = 1; i <= h; ++i){
				cin >> s;
				b[i] = '.' + s;
				for(int j = 1; j <= w; ++j){
					cr[i][j] = cr[i][j - 1] + (b[i][j] == '*');
					cc[j][i] = cc[j][i - 1] + (b[i][j] == '*');
				}
			}

			s = seq(1, 1, h, w);
			cout << s << '\n';
		}
		cout << "#\n";
	}
}
accuracy: 1
time_ms: 60
memory_kb: 2332
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

struct Term {
    enum TermType {
        GLYPH,
        SEQUENCE,
    } type;

    Term(TermType type) : type(type) {}
    virtual ~Term() {}

    virtual void print() = 0;
};

struct Glyph : public Term {
    vector<string> pattern;
    char ch;
    int height, width;

    Glyph(const vector<string> &p, char ch) : Term(Term::GLYPH), pattern(p), ch(ch), height(p.size()), width(p[0].size()) {}
    virtual ~Glyph() {}

    bool match(const vector<string> &field, int r, int c, bool flipped) const {
        for(int dr = 0; dr < height; ++dr) {
            for(int dc = 0; dc < width; ++dc) {
                const int pc = flipped ? width-dc-1 : dc;
                if(field[r+dr][c+dc] != pattern[dr][pc]) return false;
            }
        }
        return true;
    }

    virtual void print() {
        cout << ch;
    }
};

struct Sequence : public Term {
    vector<Term*> terms;
    bool box;

    Sequence(bool box=false) : Term(Term::SEQUENCE), box(box) {}

    void reverse() {
        ::reverse(terms.begin(), terms.end());
    }

    virtual void print() {
        if(box) cout << "[";
        for(Term *t : terms) {
            t->print();
        }
        if(box) cout << "]";
    }
};

vector<Glyph*> glyphs;

bool empty_column(const vector<string> &field, const int start_r, const int start_c, const int h) {
    for(int dr = 0; dr < h; ++dr) {
        if(field[start_r + dr][start_c] != '.') return false;
    }
    return true;
}

bool empty_row(const vector<string> &field, const int start_r, const int start_c, const int w) {
    for(int dc = 0; dc < w; ++dc) {
        if(field[start_r][start_c + dc] != '.') return false;
    }
    return true;
}

Glyph* glyph(const vector<string> &field, const int start_r, const int start_c, const int w, const int h, const bool flipped=false) {
    for(Glyph *g : glyphs) {
        if(g->width == w && g->height == h) {
            if(g->match(field, start_r, start_c, flipped)) return g;
        }
    }
    return nullptr;
}

Sequence* sequence(const vector<string> &field, const int start_r, const int start_c, const int w, const int h, const bool box) {
    Sequence *seq = new Sequence(box);
    int phase = 0;

parse:
    seq->terms.clear();
    for(int c = start_c; c < start_c + w; ) {
        if(!empty_column(field, start_r, c, h)) {
            // determine bounding box
            int bw = 1;
            while(c+bw < start_c+w && !empty_column(field, start_r, c+bw, h)) ++bw;
            int bt = start_r;
            while(empty_row(field, bt, c, bw)) ++bt;
            int bh = start_r + h - bt;
            while(empty_row(field, bt+bh-1, c, bw)) --bh;
            //cout << bt << ' ' << c << ' ' << bh << ' ' << bw << endl;
            Glyph *g = nullptr;
            if(phase == 0) {
                g = glyph(field, bt, c, bw, bh);
            }
            if(!g) {
                g = glyph(field, bt, c, bw, bh, true);
                if(phase == 0 && g) {
                    phase = 1;
                    goto parse;
                }
            }
            if(g) {
                seq->terms.push_back(g);
            } else {
                Sequence *s = sequence(field, bt+1, c+1, bw-2, bh-2, true);
                seq->terms.push_back(s);
            }
            c += bw;
        } else {
            ++c;
        }
    }
    if(phase == 1) {
        seq->reverse();
    }
    return seq;
}

bool solve() {
    int N, M;
    if(!(cin >> N >> M)) return false;
    if(!N && !M) return false;
    //cin.ignore();

    glyphs.clear();
    for(int i = 0; i < N; ++i) {
        char ch;
        int H, W;
        cin >> ch >> H >> W;
        vector<string> pat(H);
        for(int j = 0; j < H; ++j) {
            cin >> pat[j];
        }
        glyphs.push_back(new Glyph(pat, ch));
    }
    for(int _ = 0 ; _ < M; ++_) {
        int H, W;
        cin >> H >> W;
        vector<string> field(H);
        for(int i = 0; i < H; ++i) {
            cin >> field[i];
        }
        Sequence *seq = sequence(field, 0, 0, W, H, false);
        seq->print();
        cout << endl;
    }
    cout << "#" << endl;
    for(Glyph *g : glyphs) {
        delete g;
    }
    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);

    while(solve()) ;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 2048
final_rank: 2