← Home
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0,del##i##verme=int(n);i<del##i##verme;++i)
#define rep1(i,n) for(int i=1,parano##i##a=int(n);i<=parano##i##a;++i)
#define per(i,n) for(int i=int(n)-1;i>=0;--i)
#define per1(i,n) for(int i=int(n);i>=1;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define y0 LingLuo
#define y1 VividCycle
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using namespace std;
const ll mod1=998244353;
const ll mod2=1000000007;
unsigned time_related_rand()
{
	return unsigned(std::chrono::steady_clock::now().time_since_epoch().count());
}
#define P 1
#define Q 2 
#define LEAF 0
namespace PQTree{
	int n;
	vector<int> g[1000005];int cnt=0;
	int stk[1000005],ct;
	int type[1000005];
	int color[1000005];
	int root;
	int NewNode()
	{
		if(ct) return stk[ct--];
		return ++cnt;
	}
	void fail()
	{
		cout<<"NO\n";
		exit(0);
	}
	void print_tree(int x)
	{
		if(type[x]==LEAF)
		{
			cout<<char(96+x);
		}
		else if(type[x]==P)
		{
			cout<<"P{";
			for(int y:g[x])
			{
				print_tree(y);
			}
			cout<<"}";
		}
		else
		{
			cout<<"Q{";
			for(int y:g[x])
			{
				print_tree(y);
			}
			cout<<"}";
		}
	}
	void print_tree()
	{
		print_tree(root);cout<<'\n';
	}
	int NewNode(const vector<int>&vc,int tp)
	{
		if(int(vc.size())==1) return vc[0];
		int tmp=NewNode();
		type[tmp]=tp;
		g[tmp]=vc;
		return tmp;
	}
	void Delete(int x)
	{
		g[x].clear();
		stk[++ct]=x;
	}
	void init(int N)
	{
		n=N;
		rep1(i,cnt) g[i].clear();
		ct=0;cnt=n;
		root=NewNode();g[root].reserve(n);
		rep1(i,n) g[root].pb(i);
		rep1(i,n) type[i]=LEAF;
		type[root]=P;
	}
	void find_color(int x)
	{
		if(type[x]==LEAF) return ;
		color[x]=0;
		for(int y:g[x])
		{
			find_color(y);
			color[x]|=color[y];
		}
	//	cout<<"color [ "<<x<<" ] = "<<color[x]<<endl;
	}
	vector<int> temp;
	vector<int> white,black,gray;
	bool is_sorted(int x)// x is Q
	{
		int lst=0;
		for(int y:g[x])
		{
			int cur=1^color[y];
			if(cur<lst) return false;
			lst=cur;
		}
		return true;
	}
	void split(int x)// add split(x) after temp
	{
		if(color[x]==1||color[x]==2)
		{
			temp.pb(x);return ;
		}
		if(type[x]==P)
		{
			white.clear();
			black.clear();
			int cntg=0,target=0;
			for(int y:g[x])
			{
				if(color[y]==1) white.pb(y);
				else if(color[y]==2) black.pb(y);
				else
				{
					++cntg;target=y;
				}
			}
			if(cntg>=2)
			{
				fail();
			}
			int qwq=0;if(!black.empty()) qwq=NewNode(black,P);
			if(!white.empty()) temp.pb(NewNode(white,P));
			if(cntg) split(target);
			if(qwq) temp.pb(qwq);
			Delete(x);
			return ;
		}
		if(!is_sorted(x))
		{
			reverse(g[x].begin(),g[x].end());
			if(!is_sorted(x))
			{
				fail();
			}
		}
		int cntg=0;
		for(int y:g[x]) if(color[y]==3) ++cntg;
		if(cntg>=2) fail();
		for(int y:g[x])
		{
			if(color[y]==3) split(y);
			else temp.pb(y);
		}
		Delete(x);
	}
	void reduce(int x)
	{
		while(int(g[x].size())==1&&g[x][0]>n)
		{
			int cur=g[x][0];
			g[x].swap(g[cur]);
			type[x]=type[cur];
			Delete(cur);
		}
		for(int y:g[x])
		{
			reduce(y);
		}
	}
	int solve(int x)
	{
	//	cout<<"? solve "<<x<<" color = "<<color[x]<<" type = "<<"LPQ"[type[x]]<<endl;
		if(color[x]==1||color[x]==2) return x;
		if(type[x]==P)
		{
			white.clear();
			black.clear();
			gray.clear();
			for(int y:g[x])
			{
				if(color[y]==1) white.pb(y);
				else if(color[y]==2) black.pb(y);
				else if(color[y]==3) gray.pb(y);
			}
		//	cout<<"?! "<<gray.size()<<" gray nodes"<<endl;
			if(int(gray.size())>2)
			{
				fail();
			}
			int cur=0;if(!black.empty()) cur=NewNode(black,P);
			int res=NewNode();type[res]=P;g[res].swap(white);
			white.clear();black.clear();
			if(int(gray.size())==0)
			{
				if(cur) g[res].pb(cur);
				Delete(x);
				return res;
			}
			if(int(gray.size())==1&&cur==0)
			{
				g[res].pb(solve(gray[0]));
				Delete(x);
				return res;
			}
			int res2=NewNode();
			g[res].pb(res2);
			type[res2]=Q;
			if(int(gray.size())==1)
			{
				temp.clear();
		//		print_tree(gray[0]);
				split(gray[0]);
		//		cout<<"split -> ";
		//		for(int y:temp)
		//		{
		//			print_tree(y);cout<<" ";
		//		}
		//		cout<<endl;
				g[res2].swap(temp);
				if(cur) g[res2].pb(cur);
				Delete(x);
				return res;
			}
			temp.clear();split(gray[0]);g[res2].swap(temp);
			temp.clear();if(cur)g[res2].pb(cur);split(gray[1]);reverse(temp.begin(),temp.end());
			for(int y:temp) g[res2].pb(y);
			Delete(x);
			return res; 
		}
		int l=0,r=int(g[x].size())-1;
		while(color[g[x][l]]==1) ++l;
		while(color[g[x][r]]==1) --r;
		for(int i=l+1;i<=r-1;++i) if(color[g[x][i]]!=2)
		{
			fail();
		}
		int res=NewNode();type[res]=Q;
		if(l==r&&color[g[x][l]]==3)
		{
			int res2=solve(g[x][l]);
			g[res].swap(g[x]);g[res][l]=res2;
			Delete(x);
			return res;
		}
		for(int y:g[x])
		{
			if(color[y]!=3)
			{
				g[res].pb(y);
			}
			else
			{
				temp.clear();
				split(y);
				if(y==g[x][r]) reverse(temp.begin(),temp.end());
				for(int z:temp) g[res].pb(z);
			}
		}
		Delete(x);
		return res; 
	}
	void add_constraint(int cl[])// 0 and 1
	{
		rep1(i,n) color[i]=cl[i]+1;
		find_color(root);
		root=solve(root);
	//	print_tree();
		reduce(root);
	}
	ll fac[100005];
	ll calc_result(int x)
	{
		if(type[x]==LEAF) return 1;
		ll xx=1;
		for(int y:g[x]) xx=xx*calc_result(y)%mod1;
		if(type[x]==Q)
		{
			if(int(g[x].size())>1) xx=xx*2%mod1;
		}
		else
		{
			xx=xx*fac[g[x].size()]%mod1;
		}
		return xx;
	}
	ll calc_result()
	{
		fac[0]=1;
		rep1(i,n) fac[i]=fac[i-1]*i%mod1;
		return calc_result(root);
	}
	vector<int> perm;
	void find_perm(int x)
	{
		if(type[x]==LEAF)
		{
			perm.pb(x);return ;
		}
		for(int y:g[x]) find_perm(y);
	}
	vector<int> find_perm()
	{
		perm.clear();
		find_perm(root);
		return perm;
	}
};
int t,n,m;string s[1005],ts;
int c[100005];
vector<int> answer;
void query()
{
	cin>>n;
	PQTree::init(n);
	rep1(i,n)
	{
		cin>>s[i];
		rep1(j,n) c[j]=int((s[i][j-1])&1);
//		cout<<"? add"<<endl;
//		PQTree::print_tree();
		PQTree::add_constraint(c); 
//		cout<<"added"<<endl;
	}
//	PQTree::print_tree();
	answer=PQTree::find_perm();
//	cout<<answer[0]<<'\n';
	cout<<"YES\n";
	rep1(i,n)
	{
		ts="";
		for(int x:answer) ts+=s[i][x-1];
		cout<<ts<<'\n';
	}
}
int main()
{
	ios_base::sync_with_stdio(false);cin.tie(0);
	t=1;
	while(t--)query();
	return 0;
}
/* things to check
1.  int overflow or long long memory need
2.  recursion/array/binary search/dp/loop bounds
3.  precision
4.  special cases(n=1,bounds)
5.  delete debug statements
6.  initialize(especially multi-tests)
7.  = or == , n or m ,++ or -- , i or j , > or >= , < or <=
8.  keep it simple and stupid
9.  do not delete, use // instead
10. operator priority
11. is there anything extra to output?
12. ...
*/
 
/* something to think about
1. greedy? dp? searching? dp with matrix/ segment tree? binary search?
2. If contains "not", why not ?????? or few affect?
*/