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 (Clang 3.8.0) (judge verdict: Wrong Answer)

#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <stack>
#include <tuple>
#include <bitset>
#include <algorithm>
#include <functional>
#include <utility>
#include <iomanip>

#define int long long int
#define rep(i, n) for(int i = 0; i < (n); ++i)

using namespace std;

typedef pair<int, int> P;
typedef pair<char, char> PC;

const int INF = 1e15;
const int MOD = 1e9+7;

class pair_combination{
    private:
        int n;
        vector<bool> used;
        vector<P> tmp;
        vector<vector<P>> pairs;

        void make(int p, int fst){
            if((int)tmp.size() == n / 2){
                pairs.push_back(tmp);
                cout << endl;
                return;
            }

            if(used[p]){
                return;
            }
            used[p] = true;

            for(int i = p+1; i < n; i++){
                if(used[i]){
                    continue;
                }
                used[i] = true;
                tmp.emplace_back(p, i);
                int next;
                for(next = fst; next < n; next++){
                    if(not used[next]){
                        break;
                    }
                }
                make(next, fst);
                used[i] = false;
                tmp.pop_back();
            }
            used[p] = false;
        }

    public:
        pair_combination(int n)
            :n(n), used(n, false){
                make(0, 0);
                if(n % 2 == 1){
                    make(1, 1);
                }
            }

        vector<vector<P>> get_pairs(){
            return pairs;
        }
};

signed main(){
    int h, w;
    cin >> h >> w;

    vector<vector<char>> s(h, vector<char>(w));
    rep(i, h){
        rep(j, w){
            cin >> s[i][j];
        }
    }

    pair_combination pc(h);
    vector<vector<P>> p = pc.get_pairs();

    rep(i, (int)p.size()){
        vector<int> pos(h, -1);
        vector<bool> usedP(h, false);
        rep(j, (int)p[i].size()){
            pos[j] = p[i][j].first;
            pos[h-1-j] = p[i][j].second;
            usedP[pos[j]] = true;
            usedP[pos[h-1-j]] = true;
        }

        if(h % 2 == 1){
            int idx;
            int unused;
            rep(i, h){
                if(pos[i] == -1){
                    idx = i;
                }
                if(not usedP[i]){
                    unused = i;
                }
            }
            pos[idx] = unused;
        }

        vector<string> rows(w);
        rep(j, w){
            rep(k, h){
                rows[j].push_back(s[pos[k]][j]);
            }
        }

        vector<bool>used(w, false);
        rep(j, w){
            if(used[j]){
                continue;
            }

            rep(k, w){
                if(used[k]){
                    continue;
                }
                if(j == k){
                    continue;
                }
                string tmp = rows[k];
                reverse(tmp.begin(), tmp.end());
                if(rows[j] == tmp){
                    used[j] = true;
                    used[k] = true;
                    break;
                }
            }
        }

        int cnt = 0;
        int idx = 0;
        rep(j, w){
            if(not used[j]){
                cnt++;
                idx = j;
            }
        }

        bool ok = cnt == 0;
        if(cnt == 1){
            string tmp = rows[idx];
            reverse(tmp.begin(), tmp.end());
            if(rows[idx] == tmp){
                ok = true;
            }
        }

        if(ok){
            cout << "YES" << endl;
            return 0;
        }
    }
    cout << "NO" << endl;

    return 0;
}