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

#include <bits/stdc++.h>

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef unsigned int ui32;
const long long INFLL = 1e18;

using namespace std;

bool can(string &s3, string &s4) {
    if (s3[0] != s4.back() || s3.back() != s4[0]) {
        return false;
    }
    vector<int> cnt(26, 0);
    for (auto ch : s3) {
        ++cnt[ch - 'a'];
    }
    for (auto ch : s4) {
        --cnt[ch - 'a'];
    }
    for (int i = 0; i < 26; i++) {
        if (cnt[i]) {
            return false;
        }
    }
    string s1 = s3;
    string s2 = s4;
    int n = (int)s1.size();
    for (int i = 1, j = n - 2; i < j; i++, j--) {
        bool ok = false;
        for (int l = i; l <= j && !ok; l++) {
            for (int r = i; r <= j && !ok; r++) {
                if (l == r) {
                    continue;
                }
                if (s1[l] == s2[r] && s1[r] == s2[l]) {
                    ok = true;
                    swap(s1[i], s1[l]);
                    swap(s1[j], s1[r]);
                    swap(s2[i], s2[l]);
                    swap(s2[j], s2[r]);
                }
            }
        }
        if (!ok) {
            return false;
        }
    }
    reverse(s2.begin(), s2.end());
    assert(s1 == s2);
    return true;
}

void swapCol(vector<string> &vec, int l, int r) {
    int n = (int)vec.size();
    for (int i = 0; i < n; i++) {
        swap(vec[i][l], vec[i][r]);
    }
}

int calc(int mask) {
    int cnt = 0;
    for (int i = 0; i < 30; i++) {
        if (mask & (1 << i)) {
            ++cnt;
        }
    }
    return cnt;
}

bool go(vector<string> vec) {
    if (vec.empty() || vec[0].empty()) {
        return true;
    }
    int n = (int)vec.size();
    int m = (int)vec[0].size();
    if (n == 1) {
        int mask = 0;
        for (int i = 0; i < m; i++) {
            mask ^= (1 << (vec[0][i] - 'a'));
        }
        return calc(mask) <= 1;
    }
    if (m == 1) {
        int mask = 0;
        for (int i = 0; i < n; i++) {
            mask ^= (1 << (vec[i][0] - 'a'));
        }
        return calc(mask) <= 1;
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) {
                continue;
            }
            for (int l = 0; l < m; l++) {
                for (int r = 0; r < m; r++) {
                    if (l == r) {
                        continue;
                    }
                    swapCol(vec, 0, l);
                    swapCol(vec, r, m - 1);
                    swap(vec[0], vec[i]);
                    swap(vec[j], vec[n - 1]);
                    if (!can(vec[0], vec[n - 1])) {
                        swapCol(vec, 0, l);
                        swapCol(vec, r, m - 1);
                        swap(vec[0], vec[i]);
                        swap(vec[j], vec[n - 1]);
                        continue;
                    }
                    string t1, t2;
                    for (int k = 0; k < n; k++) {
                        t1 += vec[k][0];
                        t2 += vec[k][m - 1];
                    }
                    if (!can(t1, t2)) {
                        swapCol(vec, 0, l);
                        swapCol(vec, r, m - 1);
                        swap(vec[0], vec[i]);
                        swap(vec[j], vec[n - 1]);
                        continue;
                    }
                    vector<string> nw(n - 2);
                    for (int x = 1; x < n - 1; x++) {
                        for (int y = 1; y < m - 1; y++) {
                            nw[x - 1] += vec[x][y];
                        }
                    }
                    if (go(nw)) {
                        return true;
                    }
                    swapCol(vec, 0, l);
                    swapCol(vec, r, m - 1);
                    swap(vec[0], vec[i]);
                    swap(vec[j], vec[n - 1]);
                }
            }
        }
    }
    return false;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    //freopen("input.txt", "r", stdin);
    //freopen("input.txt", "w", stdout);

    int h, w;
    cin >> h >> w;
    vector<string> vec;
    for (int i = 0; i < h; i++) {
        string s;
        cin >> s;
        vec.push_back(s);
    }
    if (go(vec)) {
        cout << "YES\n";
    } else {
        cout << "NO\n";
    }
    return 0;
}