#define _CRT_SECURE_NO_WARNINGS
#define _USE_MATH_DEFINES
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

typedef long long ll, lint;
typedef long double ldouble;

#define sz(v) ((int) (v).size())
#define FOR(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define For(i, n) for (int (i) = 0; (i) < (n); (i)++)
#define all(v) (v).begin(), (v).end()

#define mp make_pair
#define pb push_back
#define fst first
#define snd second

template<class T>
string to_string(T arr, int len = 1e9) {
    stringstream ss;
    int i = 0;
    for (auto item : arr) {
        ss << item << ' ';
        if (++i == len)
            break;
    }
    return ss.str();
}

#ifdef LOCAL
    #define dbg(expr) cout << "[line " << __LINE__ << "] " << (#expr) << ": " << (expr) << endl;
#else
    #define dbg(expr) (void) 0;
#endif


bool check_matrix(const vector<int>& row_mapping, const vector<int>& column_mapping, const vector<string>& field) {
    int h = row_mapping.size();
    int w = column_mapping.size();
    //static bool mask[12];
    //fill(mask, mask + 12, false);
    For (i, h) {
        int r = row_mapping[i];
        For (j, w) {
            int c = column_mapping[j];
            if (field[i][j] != field[r][c])
                return false;
        }
    }
    /*
    cerr << to_string(row_mapping) << endl;
    cerr << to_string(column_mapping) << endl;
    cerr << endl;
    */
    return true;
}

bool check_columns(int ind, const vector<string>& field, vector<int>& mapping, vector<int>& mask, vector<int>& row_mapping, bool flag) {
    int h = mapping.size();
    if (ind == h) {
        return true;
        //return check_matrix(row_mapping, mapping, field);
    }
    if (mask[ind])
        return check_columns(ind + 1, field, mapping, mask, row_mapping, flag);
    mask[ind] = true;
    if (h % 2 == 1 && !flag) {
        mapping[ind] = ind;
        if (check_columns(ind + 1, field, mapping, mask, row_mapping, true))
            return true;
    }
    for (int i = ind + 1; i < h; i++) {
        if (mask[i])
            continue;
        bool err = false;
        For (j, sz(field)) {
            int r = row_mapping[j];
            if (field[j][ind] != field[r][i]) {
                err = true;
                break;
            }
        }
        if (err)
            continue;
        mask[i] = true;
        mapping[ind] = i;
        mapping[i] = ind;
        if (check_columns(ind + 1, field, mapping, mask, row_mapping, flag))
            return true;
        mask[i] = false;
    }
    mask[ind] = false;
    return false;
}

bool check(int ind, const vector<string>& field, vector<int>& mapping, vector<int>& mask, bool flag) {
    int h = field.size();
    if (ind == h) {
        vector<int> temp(field.front().size());
        vector<int> column_mapping(field.front().size());
        return check_columns(0, field, column_mapping, temp, mapping, false);
    }
    if (mask[ind])
        return check(ind + 1, field, mapping, mask, flag);
    mask[ind] = true;
    if (h % 2 == 1 && !flag) {
        mapping[ind] = ind;
        if (check(ind + 1, field, mapping, mask, true))
            return true;
    }
    for (int i = ind + 1; i < h; i++) {
        if (mask[i])
            continue;
        mask[i] = true;
        mapping[ind] = i;
        mapping[i] = ind;
        if (check(ind + 1, field, mapping, mask, flag))
            return true;
        mask[i] = false;
    }
    mask[ind] = false;
    return false;
}

int main() {
#ifndef LOCAL
    cin.tie(0);
    ios_base::sync_with_stdio(false);
#endif

    int h, w;
    cin >> h >> w;
    vector<string> field(h);
    For (i, h)
        cin >> field[i];
    vector<int> mapping(h), mask(h);
    if (check(0, field, mapping, mask, false)) {
        cout << "YES" << endl;
    } else
        cout << "NO" << endl;
}


Measured memory_bytes: 256