#include<bits/stdc++.h>
#define INF	0x3f3f3f3f
#define	LL	long long
#define	MAXN	15
#define	MAXC	28
using namespace std;
int n, m, w[MAXN][MAXN], hasx[MAXN][MAXC], hasy[MAXN][MAXC], x[MAXN], y[MAXN], fla, tmp[MAXN], usedx[MAXN], usedy[MAXN];
char s[MAXN][MAXN];

template <typename T> void chkmin(T &x, T y){x = min(x, y);}
template <typename T> void chkmax(T &x, T y){x = max(x, y);}
template <typename T> void read(T &x){
	x = 0; int f = 1; char ch = getchar();
	while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
	while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
	x *= f;
}

void dfsy(int dep){
	if (fla) return;
	if (2 * (dep - 1) >= m - 1){
		if (m & 1) {
			memset(tmp, 0, sizeof(tmp));
			for (int i = 1; i <= m; ++i)
				tmp[y[i]] = 1;
			for (int i = 1; i <= m; ++i)
				if (!tmp[i]) {y[m / 2 + 1] = i; break;}
		}
		int ff = 1;
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= m; ++j)
				if (w[x[i]][y[j]] != w[x[n - i + 1]][y[m - j + 1]]) {ff = 0; break;}
		if (ff) fla = 1;
		return;
	}
	for (int i = 1; i <= m; ++i){
		if (usedy[i]) continue;
		for (int j = i + 1; j <= m; ++j){
			if (usedy[j]) continue;
			int ff = 0;
			for (int t = 1; t <= 26; ++t)
				if (hasy[i][t] != hasy[j][t]) {ff = 1; break;}
			if (ff) continue;
			usedy[i] = usedy[j] = 1;
			y[dep] = i, y[m - dep + 1] = j;
			dfsy(dep + 1);
			usedy[i] = usedy[j] = 0;
			y[dep] = y[m - dep + 1] = 0;
		}
	}
}

void dfsx(int dep){
	if (fla) return;
	if (2 * (dep - 1) >= n - 1){
		if (n & 1) {
			memset(tmp, 0, sizeof(tmp));
			for (int i = 1; i <= n; ++i)
				tmp[x[i]] = 1;
			for (int i = 1; i <= n; ++i)
				if (!tmp[i]) {x[n / 2 + 1] = i; break;}
		}
		dfsy(1);
		return;
	}
	for (int i = 1; i <= n; ++i){
		if (usedx[i]) continue;
		for (int j = i + 1; j <= n; ++j){
			if (usedx[j]) continue;
			int ff = 0;
			for (int t = 1; t <= 26; ++t)
				if (hasx[i][t] != hasx[j][t]) {ff = 1; break;}
			if (ff) continue;
			usedx[i] = usedx[j] = 1;
			x[dep] = i, x[n - dep + 1] = j;
			dfsx(dep + 1);
			usedx[i] = usedx[j] = 0;
			x[dep] = x[n - dep + 1] = 0;
		}
	}
}

int main(){
	read(n), read(m);
	for (int i = 1; i <= n; ++i)
		scanf("%s", s[i] + 1);
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			w[i][j] = s[i][j] - 'a' + 1;
	for (int i = 1; i <= n; ++i)
		for (int j = 1; j <= m; ++j)
			++hasx[i][w[i][j]], ++hasy[j][w[i][j]];
	int tot;
	memset(tmp, 0, sizeof(tmp)); tot = 0;
	for (int i = 1; i <= n; ++i){
		for (int j = 1; j < i; ++j){
			if (tmp[j]) continue;
			int ff = 0;
			for (int t = 1; t <= 26; ++t)
				if (hasx[i][t] != hasx[j][t]) {ff = 1; break;}
			if (ff == 0) {tmp[i] = tmp[j] = 1; break;}
		}
	}
	for (int i = 1; i <= n; ++i)
		if (tmp[i] == 0) ++tot;
	if (n & 1) {if (tot > 1) {printf("NO\n"); return 0;}}
	else {if (tot > 0) {printf("NO\n"); return 0;}}
	memset(tmp, 0, sizeof(tmp)); tot = 0;
	for (int i = 1; i <= m; ++i){
		for (int j = 1; j < i; ++j){
			if (tmp[j]) continue;
			int ff = 0;
			for (int t = 1; t <= 26; ++t)
				if (hasy[i][t] != hasy[j][t]) {ff = 1; break;}
			if (ff == 0) {tmp[i] = tmp[j] = 1; break;}
		}
	}
	for (int i = 1; i <= m; ++i)
		if (tmp[i] == 0) ++tot;
	if (m & 1) {if (tot > 1) {printf("NO\n"); return 0;}}
	else {if (tot > 0) {printf("NO\n"); return 0;}}
	dfsx(1);
	if (fla) printf("YES\n");
	else printf("NO\n");
	return 0;
}

Measured memory_bytes: 256