// 基本テンプレート
 
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <string>
#include <cstring>
#include <deque>
#include <list>
#include <queue>
#include <stack>
#include <vector>
#include <utility>
#include <algorithm>
#include <map>
#include <set>
#include <complex>
#include <cmath>
#include <limits>
#include <cfloat>
#include <climits>
#include <ctime>
#include <cassert>
#include <numeric>
#include <fstream>
#include <functional>
using namespace std;
 
#define rep(i,a,n) for(int (i)=(a); (i)<(n); (i)++)
#define repq(i,a,n) for(int (i)=(a); (i)<=(n); (i)++)
#define repr(i,a,n) for(int (i)=(a); (i)>=(n); (i)--)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define int long long int
 
template<typename T> void chmax(T &a, T b) {a = max(a, b);}
template<typename T> void chmin(T &a, T b) {a = min(a, b);}
template<typename T> void chadd(T &a, T b) {a = a + b;}
 
typedef pair<int, int> pii;
typedef long long ll;
 
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
const ll INF = 1001001001001001LL;
const ll MOD = 1000000007LL;

int H, W, answerFlag = false, cnt = 0;
vector<string> board;

bool comp(string a, string b) {
    rep(i,0,H) if(a[i] != b[H-1-i]) return false;
    return true;
}

bool solve(vector<int> perm) {
    vector<string> tmp_board(H), col_board(W, "");
    vector<bool> appeared(H);
    rep(i,0,H) {
        if(perm[i] > 0) {
            if(appeared[perm[i]]) {
                tmp_board[perm[i]-1] = board[i];
            }
            else {
                appeared[perm[i]] = true;
                tmp_board[H-perm[i]] = board[i];
            }
        }
        else {
            // center
            tmp_board[H/2] = board[i];
        }
    }

    rep(i,0,H) rep(j,0,W) {
        col_board[j] += tmp_board[i][j];
    }

    vector<bool> used(W);
    bool center_col = false;
    rep(i,0,W) {
        if(!used[i]) {
            bool found = false;
            rep(j,i+1,W) {
                if(!used[j] && comp(col_board[i], col_board[j])) {
                    used[i] = used[j] = found = true;
                    break;
                }
            }

            if(!found) {
                if(W % 2 == 0) return false;
                else {
                    if(comp(col_board[i], col_board[i]) && !center_col) {
                        center_col = used[i] = true;
                    }
                    else {
                        return false;
                    }
                }
            }
        }
    }
    return true;
}

void search_board(vector<int> rec, int step=0) {
    if(step == 0 && H % 2 == 1) {
        // odd number
        rep(i,0,H) if(rec[i] < 0) {
            rec[i] = 0;
            search_board(rec, step+1);
            rec[i] = -1;
        }
    }
    else {
        if(step == 0) step++;
        bool found_zero = false;
        rep(i,0,H) if(rec[i] < 0) {
            found_zero = true;
            rep(j,i+1,H) if(rec[j] < 0) {
                rec[i] = rec[j] = step;
                search_board(rec, step+1);
                rec[i] = rec[j] = -1;
            }
            break;
        }

        if(!found_zero) {
            cnt++;
            answerFlag |= solve(rec);
        }
    }
}

signed main() {
    cin >> H >> W;
    board.resize(H);
    rep(i,0,H) cin >> board[i];

    search_board(vector<int>(H, -1));
    cout << (answerFlag ? "YES" : "NO") << endl;
    // fprintf(stderr, "cnt = %lld\n", cnt);
    return 0;
}

Measured memory_bytes: 384