#include <iostream>
#include <algorithm>
#include <iomanip>
#include <string>
#include <functional>
#include <utility>
#include <queue>
#include <vector>
#include <string>
#include <stack>
#define rep(i,n) for(ll i=0;i<n;i++)
using namespace std;
typedef long long int ll;
const ll  MOD = 1000000007;
typedef pair<ll,ll> P;
const ll INF = 100100100100100100;

ll H,W;
string s[20];
ll field[20][20];

bool used[20];
bool used2[20];


int main(){
  cin >> H >> W;
  rep(i,H){
    cin >> s[i];
    rep(j,W){
      field[i][j] = s[i][j] - 'a';
    }
  }

  rep(i,H){
    if(used[i]) continue;
    bool isFind = false;

    rep(j,H){
      if(i == j) continue;
      if(used[j]) continue;
      bool isOK = true;

      rep(k,20) used2[k] = false;
      ll odd_yuuyo = 0;

      rep(k,W){

        if(used2[k]) continue;
        P tmp;
        tmp.first = field[i][k];
        tmp.second = field[j][k];
        bool ff = false;
        used2[k] = true;
        rep(l,W){
          if(used2[l]) continue;
          if(field[i][l] == tmp.second && field[j][l] == tmp.first){
            //cerr << i << " " << j << " " << k << " " << l << endl;
            ff = true;
            used2[k] = true;
            used2[l] = true;
            break;
          }
        }
        if(!ff){
          if(W%2 == 1 && tmp.first == tmp.second && odd_yuuyo == 0){
            odd_yuuyo++;
          }
          else{
            isOK = false;
            break;
          }
        }
      }
      if(isOK){
        //okpair[okpair_i] = make_pair(i,j);
        //okpair_i++;
        used[i] = true;
        used[j] = true;
        isFind = true;
        break;
      }
    }
    if(!isFind){
      if(H%2 == 1){
        ll seibun[20] = {0};
        rep(j,W){
          seibun[field[i][j]]++;
        }
        ll odd_count = 0;
        rep(j,W){
          if(seibun[j]%2 != 0) odd_count++;
        }
        if(odd_count > 1){
          cout << "NO" << endl;
          return 0;
        }
      }
      else{
        cout << "NO" << endl;
        return 0;
      }
    }
  }
  rep(i,20){
    used[i] = false;
    used2[i] = false;
  }

  //cerr << "toppa" << endl;



  rep(i,W){
    //onazi seibun no retu sagasi
    if(used[i]) continue;
    bool isFind = false;

    rep(j,W){
      if(i == j) continue;
      if(used[j]) continue;
      bool isOK = true;

      rep(k,20) used2[k] = false;
      ll odd_yuuyo = 0;

      rep(k,H){

        if(used2[k]) continue;
        P tmp;
        tmp.first = field[k][i];
        tmp.second = field[k][j];
        bool ff = false;
        used2[k] = true;
        rep(l,H){
          if(used2[l]) continue;
          if(field[l][i] == tmp.second && field[l][j] == tmp.first){
            //cerr << i << " " << j << " " << k << " " << l << endl;
            ff = true;
            used2[k] = true;
            used2[l] = true;
            break;
          }
        }
        if(!ff){
          if(H%2 == 1 && tmp.first == tmp.second && odd_yuuyo == 0){
            odd_yuuyo++;
          }
          else{
            isOK = false;
            break;
          }
        }
      }
      if(isOK){
        //okpair[okpair_i] = make_pair(i,j);
        //okpair_i++;
        used[i] = true;
        used[j] = true;
        isFind = true;
        break;
      }
    }
    if(!isFind){
      if(W%2 == 1){
        ll seibun[20] = {0};
        rep(j,H){
          seibun[field[j][i]]++;
        }
        ll odd_count = 0;
        rep(j,H){
          if(seibun[j]%2 != 0) odd_count++;
        }
        if(odd_count > 1){
          cout << "NO" << endl;
          return 0;
        }
      }
      else{
        cout << "NO" << endl;
        return 0;
      }
    }
  }
  cout << "YES" << endl;
}


Measured memory_bytes: 384