#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstring>
#include<cctype>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<iomanip>
#include<sstream>
#include<cstdlib>
#include<ctime>
#include<list>
#include<deque>
#include<bitset>
#include<fstream>
#define ld double
#define ull unsigned long long
#define ll long long
#define pii pair<int,int >
#define iiii pair<int,pii >
#define mp make_pair
#define INF 1000000000
#define MOD 1000000007
#define rep(i,x) for(int (i)=0;(i)<(x);(i)++)
inline int getint()
{
	int x=0,p=1;char c=getchar();
	while (c<=32)c=getchar();
	if(c==45)p=-p,c=getchar();
	while (c>32)x=x*10+c-48,c=getchar();
	return x*p;
}
using namespace std;
//
string s[15],os[15],ans[15];
int n,m;
multiset<string>S;
//
void finit()
{
	n=getint();m=getint();
	rep(i,n)cin>>s[i];
	if(n&1)
	{
		rep(i,m)s[n].push_back('*');
		n++;
	}
}
bool doit()
{
	S.clear();
	rep(j,m)
	{
		string ss;
		rep(i,n)
		{
			if(ans[i][j]=='*')ss+=ans[n-i-1][j];
			else ss+=ans[i][j];
		}
		S.insert(ss);
	}
	bool flag=true;
	while (!S.empty())
	{
		string ss=*S.begin(),sss=ss;reverse(sss.begin(),sss.end());
		S.erase(S.begin());
		if(S.find(sss)!=S.end())
		{
			S.erase(S.find(sss));
			continue;
		}
		if(ss!=sss)return false;
		if(!flag)return false;
		flag=false;
	}
	return true;
}
bool work0(int mask,int istep)
{
	if(!mask)
	{
		//rep(i,n)cout<<ans[i]<<endl;
		if(doit())
		{
			printf("YES\n");
			return true;
		}
		return false;
	}
	int x=0;
	while (!(mask&(1<<x)))x++;
	ans[istep]=s[x];
	for(int i=x+1;i<n;i++)if((mask&(1<<i)))
	{
		ans[n-istep-1]=s[i];
		if(work0(mask^(1<<i)^(1<<x),istep+1))return true;
	}
	return false;
}
int main()
{
	finit();
	if(!work0((1<<n)-1,0))printf("NO\n");
	return 0;
}
