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: Wrong Answer)

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(){
		
		int N = H * W;
		var UF = new UnionFind(N);
		for(int i=0;i<H;i++){
			for(int j=0;j<W;j++){
				for(int k=0;k<H;k++){
					for(int l=0;l<W;l++){
						int p0 = i * W + j;
						int p1 = i * W + l;
						int p2 = k * W + j;
						int p3 = k * W + l;
						if(S[i][j] == S[k][l] && S[i][l] == S[k][j]){
							UF.Unite(p0,p1);
							UF.Unite(p0,p2);
							UF.Unite(p0,p3);
						}
					}
				}
			}
		}
		
//for(int i=0;i<N;i++) if(UF.IsRoot(i)) Console.WriteLine("{0},{1}",i,UF.MemCnt(i));
		
		HashSet<int>[] hs = new HashSet<int>[N];
		HashSet<int>[] ws = new HashSet<int>[N];
		for(int i=0;i<N;i++){
			hs[i] = new HashSet<int>();
			ws[i] = new HashSet<int>();
		}
		
		for(int i=0;i<H;i++){
			for(int j=0;j<W;j++){
				hs[UF.Parent(i * W + j)].Add(i);
				ws[UF.Parent(i * W + j)].Add(j);
			}
		}
		
		int odd = 0;
		int hodd = 0;
		int wodd = 0;
		for(int i=0;i<N;i++){
			if(hs[i].Count == 0) continue;
			if(hs[i].Count % 2 == 1 && ws[i].Count % 2 == 1) odd++;
			if(hs[i].Count % 2 == 0 && ws[i].Count % 2 == 1) hodd++;
			if(hs[i].Count % 2 == 1 && ws[i].Count % 2 == 0) wodd++;
		}
		
		int ol = N % 2;
		int wl = (W % 2 == 1) ? H / 2 : 0;
		int hl = (H % 2 == 1) ? W / 2 : 0;
		if(odd <= ol && wodd <= wl && hodd <= hl){
			Console.WriteLine("YES");
		} else {
			Console.WriteLine("NO");
		}
		
		
	}
	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;
		}
	}
	
}