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++14 (GCC 5.4.1) (judge verdict: Runtime Error)

#include <bits/stdc++.h>

using namespace std;

const int N = 514;
const int E = (2e5) * 2;

int n, m;
char ip[N][N];

int mat[N];

struct Graph{
  int to[E],bro[E],head[N],e;
  int lnk[N],vis[N],stp,n;
  void init( int _n ){
    stp = 0; e = 1; n = _n;
    for( int i = 1 ; i <= n ; i ++ )
      lnk[i] = vis[i] = 0;
  }
  void add_edge(int u,int v){
    to[e]=v,bro[e]=head[u],head[u]=e++;
    to[e]=u,bro[e]=head[v],head[v]=e++;
  }
  bool dfs(int x){
    vis[x]=stp;
    for(int i=head[x];i;i=bro[i]){
      int v=to[i];
      if(!lnk[v]){
        lnk[x]=v,lnk[v]=x;
        return true;
      }else if(vis[lnk[v]]<stp){
        int w=lnk[v];
        lnk[x]=v,lnk[v]=x,lnk[w]=0;
        if(dfs(w)){
          return true;
        }
        lnk[w]=v,lnk[v]=w,lnk[x]=0;
      }
    }
    return false;
  }
  int solve(){
    int ans = 0;
    for(int i=1;i<=n;i++)
      if(!lnk[i]){
        stp++; ans += dfs(i);
      }
    return ans;
  }
} graph;

bool ans;

void chk() {
  for (int i = 0; i < n; ++i) if (mat[i] == -1) return;
  graph.init(m);
  for (int i = 0; i < m; ++i) {
    for (int j = i + 1; j < m; ++j) {
      bool good = 1;
      for (int k = 0; k < n; ++k) {
        if (ip[k][i] != ip[mat[k]][j] || ip[k][j] != ip[mat[k]][i]) {
          good = 0;
          break;
        }
      }
      if (good) graph.add_edge(i+1, j+1);
    }
  }
  if (graph.solve() >= m/2) {
    ans = 1;
    return;
  }
}

void dfs(int i) {
  if (ans) return;
  if (i == n) {
    chk();
  }
  if (mat[i] != -1) {
    dfs(i + 1);
    return;
  }
  for (int j = i; j < n; ++j) if (mat[j] == -1) {
    if (j == i && n % 2 == 0) continue;
    mat[j] = i;
    mat[i] = j;
    dfs(i + 1);
    if (ans) return;
    mat[j] = -1;
    mat[i] = -1;
  }
  return;
}

int main() {
  cin >> n >> m;
  for (int i = 0; i < n; ++i) cin >> ip[i];
  fill(mat, mat+n, -1);
  dfs(0);
  cout << (ans? "YES": "NO") << endl;
}