Problem:
Score : 700 points

Problem Statement

There is an H \times W grid (H vertical, W horizontal), where each square contains a lowercase English letter.
Specifically, the letter in the square at the i-th row and j-th column is equal to the j-th character in the string S_i.

Snuke can apply the following operation to this grid any number of times:

Choose two different rows and swap them. Or, choose two different columns and swap them.

Snuke wants this grid to be symmetric.
That is, for any 1 \leq i \leq H and 1 \leq j \leq W, the letter in the square at the i-th row and j-th column and the letter in the square at the (H + 1 - i)-th row and (W + 1 - j)-th column should be equal.

Determine if Snuke can achieve this objective.

Constraints

1 \leq H \leq 12

1 \leq W \leq 12

|S_i| = W

S_i consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

H W
S_1
S_2
:
S_H

Output

If Snuke can make the grid symmetric, print YES; if he cannot, print NO.

Sample Input 1

2 3
arc
rac

Sample Output 1

YES

If the second and third columns from the left are swapped, the grid becomes symmetric, as shown in the image below:

Sample Input 2

3 7
atcoder
regular
contest

Sample Output 2

NO

Sample Input 3

12 12
bimonigaloaf
faurwlkbleht
dexwimqxzxbb
lxdgyoifcxid
ydxiliocfdgx
nfoabgilamoi
ibxbdqmzxxwe
pqirylfrcrnf
wtehfkllbura
yfrnpflcrirq
wvcclwgiubrk
lkbrwgwuiccv

Sample Output 3

YES

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

//written by libra9z
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <cstring>
#include <cmath>
#include <cstdlib>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,n) for (int i=0;i<(n);i++)
#define repit(it,a) for (__typeof(a.begin()) it=a.begin();it!=a.end();++it)
#define RET(p,x) return p<<x<<endl,0
#define all(a) (a).begin(),(a).end()
#define reunique(v) v.erase(unique(all(v)),v.end())
#define sz(a) (int)a.size()
#define sqr(x) ((x)*(x))
const int inf=1e9;
const ll lnf=1e18;
const int mod=1e9+7;
int h,w;
char s[13][13];
string ss[13];
int a[13];
int b[13];
void dfs1(int x,bool f)
{
	if (x==w)
	{
		puts("YES");
		exit(0);
	}
	else if (b[x]!=-1) dfs1(x+1,f);
	else
	{
		for (int i=x+1;i<w;++i)
		{
			if (b[i]!=-1) continue;
			int j;
			for (j=0;j<h;++j) if (s[j][x]!=s[a[j]][i]) break;
			if (j==h)
			{
				b[x]=i;
				b[i]=x;
				dfs1(x+1,f);
				b[x]=b[i]=-1;
			}
		}
		if (!f)
		{
			int j;
			for (j=0;j<h;++j) if (s[j][x]!=s[a[j]][x]) break;
			if (j==h)
			{
				b[x]=x;
				dfs1(x+1,true);
				b[x]=-1;
			}
		}
	}
}
void dfs2(int x,bool f)
{
	if (x==h) dfs1(0,!(w&1));
	else if (a[x]!=-1) dfs2(x+1,f);
	else
	{
		for (int i=x+1;i<h;++i)
		{
			if (a[i]!=-1) continue;
			if (ss[x]!=ss[i]) continue;
			a[x]=i;
			a[i]=x;
			dfs2(x+1,f);
			a[x]=a[i]=-1;
		}
		if (!f)
		{
			a[x]=x;
			dfs2(x+1,true);
			a[x]=-1;
		}
	}
}
int main()
{
	ios_base::sync_with_stdio(0);cin.tie();cout.tie();
	cout<<setprecision(15);
	cin>>h>>w;
	for (int i=0;i<h;++i) cin>>s[i],ss[i]=s[i],sort(ss[i].begin(),ss[i].end());
	int ui;
	for (int i=0;i<1000000000;++i)ui+=i;
	for (int i=0;i<h;++i) a[i]=-1;
	for (int i=0;i<w;++i) b[i]=-1;
	dfs2(0,!(h&1));
	cout<<"NO\n";
	return 0;
}