#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <iostream>
#include <stack>
#include <vector>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <random>
#include <chrono>
using namespace std;

int H, W;

bool palindrome(string s){
    string t = s;
    reverse(t.begin(), t.end());
    return s == t;
}

bool equal(string s, string t){
    reverse(t.begin(), t.end());
    return s == t;
}

bool match(vector<string> s, int n){
    vector<bool> used(n, 0);
    int odd = 0;
    for(int i = 0;i < n;i++){
        if(used[i])
            continue;
        for(int j = 0;j < n;j++){
            if(used[j] or (j == i))
                continue;
            if(equal(s[i], s[j])){
                used[i] = 1;
                used[j] = 1;
                break;
            }
        }
        if(!used[i]){
           if((n & 1) and odd == 0){
               if(palindrome(s[i])){
                   odd++;
                   used[i] = 1;
               }else{
                    return false;
               }
           }else{
               return false;
           } 
        }
    }
    return true;
}

string S[20];

vector<string> my_shuffle(vector<int> id){
    vector<string> ret;
    for(int i = 0;i < H;i++){
        string tmp = S[i];
        for(int j = 0;j < W;j++){
            tmp[j] = S[i][id[j]];
        }
        ret.push_back(tmp);
    }
    return ret;
}

void print(vector<int> p){
    for(auto v : p){
        cout << v << " ";
    }
    cout << endl;
}

vector<int> modify(vector<int> p){
    vector<int> odd, even;
    if(p.size() & 1){
        for(int i = 2;i < p.size();i += 2){
            even.push_back(p[i]);
        }
        even.push_back(p[0]);
    }
    else{
        for(int i = 0;i < p.size();i += 2){
            even.push_back(p[i]);
        }
    }
    for(int i = 1;i < p.size();i += 2){
        odd.push_back(p[i]);
    }
    reverse(odd.begin(), odd.end());
    for(auto v : odd){
        even.push_back(v);
    }
    return even;
}

bool dfs(int id, vector<int> p){
    if(id == (W + 1) / 2 + 1){
        p = modify(p);
        //print(p); 
        vector<string> str = my_shuffle(p);
        return match(str, H);
    }
    if(id == 1 and (W & 1)){
        bool res = false;
        for(int i = 0;i < W;i++){
            res |= dfs(id + 1, {i});
        }
        return res;
    }
    int first;
    for(int i = 0;i < W;i++){
        bool flag = false;
        for(auto v : p){
            if(v == i)
                flag = true;
        }
        if(!flag){
            first = i;
            break;
        }
    }
    vector<int> tmp = p;
    tmp.push_back(first);
    if(tmp.size() == W){
        return dfs(id + 1, tmp);
    }else{
        bool res = false;
        for(int i = 0;i < W;i++){
            bool flag = false;
            for(auto v : tmp){
                if(v == i)
                    flag = true;
            }
            if(!flag){
                vector<int> tmp1 = tmp;
                tmp1.push_back(i);
                res |= dfs(id + 1, tmp1);
            }
        }
        return res;
    }
    return false;
}

int main(){
    cin >> H >> W;
    for(int i = 0;i < H;i++){
        cin >> S[i];
    }
    if(dfs(1, {})){
        cout << "YES" << endl;
    }else{
        cout << "NO" << endl;
    }
    return 0;
}


Measured memory_bytes: 256