/* 题目: 找到所有在上面的窗口,窗口的大小最小高度和宽度均为3。 分析: 通过搜索找到左上右下的坐标,然后再判断边上或里面是否有其他的字母,另外 注意由于窗口的大小最小为3*3。由于最大为100*100,O(n^3)暴搜算法即可 注意细节: 6 10 .......... .AAAAAAAA. .A.BBB..A. .A.B.B..A. .A.BBB..A. .AAAAAAAA. */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int X = 105; char map[X][X]; int n,m; int use[27]; struct point { int x,y; }; bool bfs(int x,int y,char a) { use[a-'A'] = 1; point lt,rb; lt.x = x; lt.y = y; rb.x = x; rb.y = y; for(int i=x;i<n;i++) //找到左上右下的坐标 for(int j=y;j<m;j++) if(map[i][j]==a) { lt.x = min(lt.x,i); lt.y = min(lt.y,j); rb.x = max(rb.x,i); rb.y = max(rb.y,j); } if(rb.x-lt.x<2||rb.y-lt.y<2) //大小不符 return false; for(int i=lt.x;i<=rb.x;i++) //判断边上是否全为该字母 if(map[i][y]!=a||map[i][rb.y]!=a) return false; for(int i=lt.y;i<=rb.y;i++) if(map[lt.x][i]!=a||map[rb.x][i]!=a) return false; for(int i=lt.x+1;i<rb.x;i++) //判断里面是否有其他的窗口 for(int j=lt.y+1;j<rb.y;j++) if(map[i][j]!='.') return false; return true; } int main() { freopen("sum.in","r",stdin); freopen("sum.out","w",stdout); while(scanf("%d%d",&n,&m),n||m) { if(n<3||m<3) { printf("1\n"); continue; } for(int i=0;i<n;i++) scanf("%s",map[i]); memset(use,0,sizeof(use)); for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(map[i][j]!='.'&&!use[map[i][j]-'A']) if(bfs(i,j,map[i][j])) use[map[i][j]-'A'] = 2; for(int i=0;i<26;i++) if(use[i]==2) printf("%c",(char)('A'+i)); printf("\n"); } return 0; }