#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);
    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();
    
    if (n % 2 == 0) {
        dfs(n, vec, rem);
    }
    else {
        for (int i = 0; i < n; ++i) {
            vec.push_back(pint(i, i));
            rem.erase(i);
            dfs(n, vec, rem);
            vec.pop_back();
            rem.insert(i);
        }
    }
    
    return tmps;
}

int main() {
    while (cin >> H >> W) {
        vector<vector<pint> > hp = makecups(H);

        
        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;
            
            if (W & 1) {
                for (int w = 0; w < W; ++w) {
                    if (kinshi.count(pint(w, w))) continue;
                    dp[(1<<w)] = 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 (dp[(1<<W)-1]) res = true;
        }
        
        if (res) puts("YES");
        else puts("NO");
    }
}















Measured memory_bytes: 1980