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`.

Examples

Input

2 3
arc
rac


Output

YES


Input

3 7
atcoder
regular
contest


Output

NO


Input

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


Output

YES
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#include<bitset>
#include<map>

#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)

using namespace std;

typedef long long LL;
typedef double db;

int get(){
	char ch;
	while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');
	if (ch=='-'){
		int s=0;
		while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
		return -s;
	}
	int s=ch-'0';
	while(ch=getchar(),ch>='0'&&ch<='9')s=s*10+ch-'0';
	return s;
}

const int L = 10395+10;
const int N = 13;
const int M = (1<<12)+1;

bitset<L>cp[N][N],f[M];
int n,m;
char s[N][N];
bool bz[N];
int tp[L][N];
int k;
int ct[N];

void dfs(int x,bool tg){
	if (x>m){
		k++;
		fo(i,1,m)tp[k][i]=ct[i];
		return;
	}
	if (bz[x]){dfs(x+1,tg);return;}
	fo(i,x+1,m)
	if (!bz[i]){
		bz[x]=bz[i]=1;
		ct[x]=i,ct[i]=x;
		dfs(x+1,tg);
		ct[x]=ct[i]=0;
		bz[x]=bz[i]=0;
	}
	if (!tg&&(m&1)>0){
		bz[x]=1;
		ct[x]=x;
		dfs(x+1,1);
		ct[x]=x;
		bz[x]=0;
	}
}

int cnt[M];

int main(){
	//freopen("data.in","r",stdin);
	n=get();m=get();
	fo(i,1,n)scanf("%s",s[i]+1);
	dfs(1,0);
	fo(i,1,n){
		fo(j,i,n){
			fo(w,1,k){
				bool pd=1;
				fo(x,1,m)pd&=(s[j][tp[w][x]]==s[i][x]);
				if (pd)cp[i][j][w-1]=1;
			}
		}
	}
	if (n&1){
		fo(st,1,n)
			f[(1<<(st-1))]=cp[st][st];
	}
	else
	fo(i,0,k-1)f[0][i]=1;
	fo(i,1,(1<<n)-1)cnt[i]=cnt[i-(i&-i)]+1;
	fo(i,0,(1<<n)-1)
	if (cnt[i]+2<=n){
		int x;
		fo(w,1,n)
		if (((1<<(w-1))&i)==0){x=w;break;}
		fo(y,x+1,n)
		if (((1<<(y-1))&i)==0)f[i|(1<<(x-1))|(1<<(y-1))]=f[i|(1<<(x-1))|(1<<(y-1))]|(f[i]&cp[x][y]);
	}
	bool ans=0;
	fo(i,0,k-1)ans=ans|f[(1<<n)-1][i];
	if (ans)printf("YES\n");
	else printf("NO\n");
	return 0;
}