/*题意自己看。
思路是先找出每个字符对应矩形框的的边界,即四个角的值。
然后排个序。
对每个字符对应的矩型框,扫描在矩形框上和该字符不相同的字符,然后在这两个字符之间连一条边,
更新后一个字符的入度,有个需要注意的地方就是对每一个字符的矩形框上的不同字符,
若出现好几次,则只更新一次入度,这个可以用一个bool数组来判重。
然后图统计好之后就开始拓扑排序。
因为要按字典序输出多组解。
所有采用DFS进行拓扑。
这个题编码有难度,思路也不错,是一道值得推荐的拓扑排序。*/
#include <stdio.h>
#include <cstring>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
struct MAP
{
int r,l,u,d;
} MAP[26];
char m[31][31];
char letter[26];
bool top[31][31];
int in[31];
map <char,int> mp;
char route[31];
int n,mm,t,num;
void topsort()
{
if(t==num)
{
printf("%s\n",route);
return ;
}
for(int i=1; i<=num; i++)
{
if(in[i]==0)
{
in[i]--;
route[t++]=letter[i];
for(int j=1; j<=num; j++)
{
if(top[i][j])
in[j]--;
}
topsort();
t--;
in[i]++;
for(int j=1; j<=num; j++)
{
if(top[i][j])
in[j]++;
}
}
}
}
int main()
{
char s[31];
while(scanf("%d%d",&n,&mm)==2)
{
memset(m,0,sizeof(m));
memset(in,0,sizeof(in));
memset(top,false,sizeof(top));
num=1;
mp.clear();
for(int i=0; i<n; i++)
{
scanf("%s",s);
for(int j=0; j<strlen(s); j++)
{
m[i][j]=s[j];
if(mp[s[j]]==0&&s[j]>='A'&&s[j]<='Z')
{
letter[num]=s[j];
mp[s[j]]=num;
num++;
}
}
}
sort(letter+1,letter+num);
num--;
mp.clear();
for(int i=1; i<=num; i++)
mp[letter[i]]=i;
for(int k=1; k<=num; k++)
{
char tmp=letter[k];
MAP[k].l=MAP[k].u=10000;
MAP[k].r=MAP[k].d=-1;
for(int i=0; i<n; i++)
for(int j=0; j<mm; j++)
{
if(m[i][j]==tmp&&j<MAP[k].l) MAP[k].l=j;
if(m[i][j]==tmp&&j>MAP[k].r) MAP[k].r=j;
if(m[i][j]==tmp&&i>MAP[k].d) MAP[k].d=i;
if(m[i][j]==tmp&&i<MAP[k].u) MAP[k].u=i;
}
}
for(int k=1; k<=num; k++)
{
for(int i=MAP[k].u; i<=MAP[k].d; i++)
{
int l=MAP[k].l;
char u=m[i][l];
if(u!=letter[k]&&!top[k][mp[u]])
{
top[k][mp[u]]=true;
in[mp[u]]++;
}
}
for(int i=MAP[k].u; i<=MAP[k].d; i++)
{
int r=MAP[k].r;
char u=m[i][r];
if(u!=letter[k]&&!top[k][mp[u]])
{
top[k][mp[u]]=true;
in[mp[u]]++;
}
}
for(int i=MAP[k].l+1; i<MAP[k].r; i++)
{
int r=MAP[k].u;
char u=m[r][i];
if(u!=letter[k]&&!top[k][mp[u]])
{
top[k][mp[u]]=true;
in[mp[u]]++;
}
}
for(int i=MAP[k].l+1; i<MAP[k].r; i++)
{
int r=MAP[k].d;
char u=m[r][i];
if(u!=letter[k]&&!top[k][mp[u]])
{
top[k][mp[u]]=true;
in[mp[u]]++;
}
}
}
t=0;
memset(route,0,sizeof(route));
topsort();
}
return 0;
}