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# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

class TEST{
	static void Main(){
		Sol mySol =new Sol();
		mySol.Solve();
	}
}

class Sol{
	public void Solve(){
		
		found = false;
		int[] ar = new int[H];
		for(int i=0;i<H;i++){
			ar[i] = -1;
		}
		dfs(ar);
//Console.WriteLine("ccc:{0}",ccc);		
		Console.WriteLine(found ? "YES" : "NO");
		
	}
	
	
	bool found;
//int ccc = 0;
	void dfs(int[] ar){
//Console.WriteLine(String.Join(" ",ar));
		if(found) return;
		
		int l = -1;
		int m = -1;
		int rest = H;
		for(int i=0;i<H;i++){
			m = Math.Max(ar[i], m);
			if(ar[i] == -1 && l == -1){
				l = i;
			} else if(ar[i] != -1){
				rest--;
			}
		}
		if(rest == 0){
//ccc++;
			checkCol(ar);
			return;
		}
		
		m++;
		int strt = l;
		if(rest % 2 == 0) strt++;
		for(int j=strt;j<H;j++){
			if(ar[j] == -1){
				ar[l] = m;
				ar[j] = m;
				dfs(ar);
				ar[j] = -1;
				ar[l] = -1;
			}
		}
		ar[l] = -1;
	}
	
	void checkCol(int[] ar){
		
		int[] cnt = new int[(H + 1)/2];
		for(int i=0;i<H;i++) cnt[ar[i]]++;
		List<int>[] gp = new List<int>[(H + 1)/2];
		for(int i=0;i<(H + 1)/2;i++) gp[i] = new List<int>(2);
		for(int i=0;i<H;i++) gp[ar[i]].Add(i);
		Array.Sort(gp, (l, r) => l.Count.CompareTo(r.Count));
		Array.Reverse(gp);
		
		String[] s = new String[H];
		for(int i=0;i<gp.Length;i++){
			s[i] = S[gp[i][0]];
			if(gp[i].Count > 1){
				s[H - 1 - i] = S[gp[i][1]];
			}
		}
		
		bool[] used = new bool[W];
		int sgl = W % 2;
		bool chk = true;
		
		for(int j0=0;j0<W;j0++){
			if(used[j0]) continue;
			bool chk1 = false;
			for(int j1=j0+1;j1<W;j1++){
				if(used[j1]) continue;
				bool chk2 = true;
				for(int i=0;i<H;i++){
					chk2 &= s[i][j0] == s[H - 1 - i][j1];
				}
				if(chk2){
					chk1 = true;
					used[j0] = used[j1] = true;
					break;
				}
			}
			if(chk1) continue;
			
			// palindromic
			if(sgl == 0){
				chk = false;
				break;
			}
			bool chk3 = true;
			for(int i=0;i<H;i++){
				chk3 &= s[i][j0] == s[H - 1 - i][j0];
			}
			if(chk3){
				sgl--;
				used[j0] = true;
				continue;
			}
			chk = false;
			break;
		}
		
		if(chk) found = true;
	}
	
	
	int H, W;
	String[] S;
	public Sol(){
		var d = ria();
		H = d[0]; W = d[1];
		S = new String[H];
		for(int i=0;i<H;i++) S[i] = rs();
	}

	static String rs(){return Console.ReadLine();}
	static int ri(){return int.Parse(Console.ReadLine());}
	static long rl(){return long.Parse(Console.ReadLine());}
	static double rd(){return double.Parse(Console.ReadLine());}
	static String[] rsa(char sep=' '){return Console.ReadLine().Split(sep);}
	static int[] ria(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>int.Parse(e));}
	static long[] rla(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>long.Parse(e));}
	static double[] rda(char sep=' '){return Array.ConvertAll(Console.ReadLine().Split(sep),e=>double.Parse(e));}
}

class UnionFind{
	
	int[] parent;
	int[] mem;
	int compo;
	int N;
	public UnionFind(int n_){
		Initialize(n_);
	}
	
	public void Initialize(int n_){
		N=n_;
		parent=new int[N];
		mem=new int[N];
		for(int i=0;i<N;i++){
			parent[i]=i;
			mem[i]=1;
		}
		compo=N;
	}
	
	public int Parent(int a){
		if(parent[a]==a)return a;
		return parent[a]=Parent(parent[a]);
	}
	
	public bool IsUnited(int a,int b){
		return Parent(a)==Parent(b);
	}
	
	public void Unite(int a,int b){
		a=Parent(a);b=Parent(b);//Parent()を呼ぶことでa以上のノードは全てparentがrootになる
		if(a==b)return;
		parent[a]=b;
		mem[b]+=mem[a];
		compo-=1;
	}
	
	public bool IsRoot(int x){
		return x==parent[x];
	}
	public int MemCnt(int x){
		return mem[Parent(x)];
	}
	
	public void Dump(){
		for(int i=0;i<parent.Length;i++){
			Console.Write(i==0?"{0}":" {0}",parent[i]);
		}
		Console.WriteLine("");
	}
	
	public int Compo{
		get{
			return compo;
		}
	}
	
}