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 <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <utility>
#include <iomanip>
#include <algorithm>
#include <functional>
#include <unordered_map>
using namespace std;

#define REP(i, s) for (int i = 0; i < s; ++i)
#define ALL(v) (v.begin(), v.end())
#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
#define EACH(i, s) for (__typeof__((s).begin()) i = (s).begin(); i != (s).end(); ++i)

template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ EACH(it, P) { s << "<" << *it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ EACH(it, P) { s << "<" << it->first << "->" << it->second << "> "; } return s << endl; }


typedef pair<int,int> pint;

int H, W;
vector<string> S;

vector<vector<pint> > tmps;
void dfs(int n, vector<pint> vec, set<int> rem) {
    if (rem.empty()) {
        tmps.push_back(vec);
        return;
    }
    int f = *(rem.begin());
    rem.erase(f);
    
    if (rem.empty()) {
        vec.push_back(pint(f, f));
        dfs(n, vec, rem);
    }
    else {
        set<int> nrem = rem;
        EACH(it, nrem) {
            int s = *it;
            vec.push_back(pint(f, s));
            rem.erase(s);
            dfs(n, vec, rem);
            vec.pop_back();
            rem.insert(s);
        }
    }
}

vector<vector<pint> > makecups(int n) {
    set<int> rem;
    for (int i = 0; i < n; ++i) rem.insert(i);
    vector<pint> vec;
    tmps.clear();
    dfs(n, vec, rem);
    return tmps;
}

int main() {
    while (cin >> H >> W) {
        vector<vector<pint> > hp = makecups(H), wp = makecups(W);
        set<vector<pint> > sp;
        for (auto i : wp) sp.insert(i);
        
        /*
        COUT(hp);
        COUT(wp);
        
        COUT(hp.size());
         */
        
        S.resize(H);
        for (int i = 0; i < H; ++i) cin >> S[i];
        
        bool res = false;
        for (auto hps : hp) {
            set<pint> kinshi;
            
            bool tmp = true;
            
            for (int i = 0; i < hps.size(); ++i) {
                //if (!tmp) break;
                string s1 = S[hps[i].first];
                string s2 = S[hps[i].second];
                
                /*
                map<char,int> m1, m2;
                for (auto c : s1) m1[c]++;
                for (auto c : s2) m2[c]++;
                if (m1 != m2) tmp = false;
                 */
                
                for (int i = 0; i < s1.size(); ++i) {
                    for (int j = i; j < s1.size(); ++j) {
                        bool ok = true;
                        if (s1[i] != s2[j]) ok = false;
                        if (s1[j] != s2[i]) ok = false;
                        
                        if (!ok) {
                            kinshi.insert(pint(i, j));
                        }
                    }
                }
            }
            
            if (!tmp) continue;
            
            //COUT(kinshi);
            
            bool dp[5000];
            memset(dp, 0, sizeof(dp));
            dp[0] = true;
            for (int bit = 0; bit < (1<<W); ++bit) {
                if (!dp[bit]) continue;
                
                //cout << bitset<10>(bit) << endl;
                
                int f = 0;
                for (f = 0; f < W; ++f) {
                    if (bit & (1<<f)) continue;
                    else break;
                }
                if (f == W) break;
                for (int s = f+1; s < W; ++s) {
                    if (bit & (1<<s)) continue;
                    if (kinshi.count(pint(f, s))) continue;
                    int nbit = bit | (1<<f) | (1<<s);
                    dp[nbit] = true;
                }
            }
            
            
            if (W & 1) {
                for (int w = 0; w < W; ++w) {
                    int abit = ((1<<W)-1) - (1<<w);
                    if (dp[abit] && !kinshi.count(pint(w, w))) {
                        res = true;
                    }
                }
            }
            else {
                if (dp[(1<<W)-1]) res = true;
            }
        }
        
        if (res) puts("YES");
        else puts("NO");
    }
}