#include <bits/stdc++.h>
namespace sjtu {
class PQ_tree {
 private:
  struct Node {
    int id;
    int size;
    int sum;
    int PQ_type;
    bool tag_rev;
    std::vector<Node*> edge;
    Node(int id = 0) : id(id), PQ_type(0), tag_rev(0) { edge.clear(); }
    Node(const Node& other)
        : id(other.id),
          size(other.size),
          sum(other.sum),
          PQ_type(other.PQ_type),
          tag_rev(other.tag_rev) {
      for (int i = 0; i < other.edge.size(); i++) {
        edge.push_back(new Node(*other.edge[i]));
      }
    }
    Node& operator=(const Node& other) {
      if (this == &other) return *this;
      id = other.id;
      size = other.size;
      sum = other.sum;
      PQ_type = other.PQ_type;
      tag_rev = other.tag_rev;
      edge.clear();
      for (int i = 0; i < other.edge.size(); i++) {
        edge.push_back(new Node(*other.edge[i]));
      }
      return *this;
    }
  };
  Node* root;
  int size;
  std::vector<int> ans;
  bool* data;
  bool flag;
  class No_solution {
    int type;

   public:
    No_solution() {}
    No_solution(int x) {}
  };
  void dfs(Node*& x) {
    if (x->id) {
      x->size = 1;
      if (data[x->id])
        x->sum = 1;
      else
        x->sum = 0;
      return;
    }
    x->size = 0;
    x->sum = 0;
    for (int i = 0; i < x->edge.size(); i++) {
      Node* y = x->edge[i];
      dfs(y);
      x->size += y->size;
      x->sum += y->sum;
    }
  }
  void build() {
    root = new Node(0);
    for (int i = 1; i <= size; i++) {
      root->edge.push_back(new Node(i));
    }
  }
  void push_down(Node*& x) {
    if (x->tag_rev == 0) return;
    for (int i = 0; i < x->edge.size(); i++) {
      x->edge[i]->tag_rev ^= 1;
    }
    std::reverse(x->edge.begin(), x->edge.end());
    x->tag_rev = 0;
  }
  void get_ans(Node*& x) {
    push_down(x);
    if (x->id) ans.push_back(x->id);
    for (int i = 0; i < x->edge.size(); i++) {
      get_ans(x->edge[i]);
    }
  }
  void modify(Node* x) {
    if (x->PQ_type != 2) throw No_solution();
    x->PQ_type = 1;
    x->tag_rev = 1;
    push_down(x);
  }
  Node* P_operation(Node* x, int type) {
    std::vector<Node*> a, b, c;
    for (int i = 0; i < (int)x->edge.size(); i++) {
      Node* cur = x->edge[i];
      if (cur->size == cur->sum)
        a.push_back(cur);
      else if (cur->sum == 0)
        b.push_back(cur);
      else
        c.push_back(cur);
    }
    if ((int)c.size() > 2) throw No_solution();
    if (!(type == 0 || (int)c.size() < 2)) throw No_solution();
    if ((int)a.size() == 0 && (int)c.size() == 1) {
      if (type == 0) {
        for (int i = 0; i < (int)x->edge.size(); i++)
          if (x->edge[i] == c[0]) {
            x->edge[i] = solve(c[0], 0);
            return x;
          }
      }
    }
    Node* ta = 0;
    int sz = (int)a.size();
    if (sz) {
      if (sz == 1)
        ta = a[0];
      else {
        ta = new Node();
        ta->PQ_type = 0;
        ta->id = 0;
        ta->edge = a;
      }
    }
    std::vector<Node*> tmp;
    if (type == 0 || type == 2) {
      if ((int)c.size()) tmp.push_back(solve(c[0], 2));
    }
    if (ta != NULL) tmp.push_back(ta);
    if (type == 0) {
      if ((int)c.size() == 2) tmp.push_back(solve(c[1], 1));
    } else if (type == 1) {
      int csz = (int)c.size();
      if (csz >= 1) tmp.push_back(solve(c[csz - 1], 1));
    }
    Node* nc = 0;
    if ((int)tmp.size() == 1)
      nc = tmp[0];
    else {
      nc = new Node();
      nc->PQ_type = 2;
      nc->id = 0;
      nc->edge = tmp;
    }
    Node* nb = 0;
    if ((int)b.size() == 1)
      nb = b[0];
    else {
      nb = new Node();
      nb->PQ_type = 0;
      nb->id = 0;
      nb->edge = b;
    }
    Node* r;
    if ((int)b.size() == 0)
      r = nc;
    else {
      r = new Node();
      r->id = 0;
      if (type == 0) {
        r->PQ_type = 0;
        r->edge = b;
        r->edge.push_back(nc);
      } else {
        r->PQ_type = 1;
        if (type == 1)
          r->edge.push_back(nc), r->edge.push_back(nb);
        else
          r->edge.push_back(nb), r->edge.push_back(nc);
      }
    }
    return r;
  }
  Node* Q_operation(Node* x, int type) {
    Node* l = x->edge[0];
    Node* r = x->edge[(int)x->edge.size() - 1];
    if (type == 1 && !(l->sum == l->size || (l->sum && r->size != r->sum)))
      modify(x);
    else if (type == 2 &&
             !(r->sum == r->size || (r->sum != 0 && l->size != l->sum)))
      modify(x);
    int last = -1, flag = 0, cnt = 0, total = 0;
    for (int i = 0; i < x->edge.size(); ++i) {
      Node* y = x->edge[i];
      int w;
      if (y->size == y->sum)
        w = 2;
      else if (y->sum == 0)
        w = 0;
      else
        w = 1;
      if (last != -1) {
        if (w > last && type == 1) throw No_solution();
        if (w < last && type == 2) throw No_solution();
        if (!w && last) flag = 1;
        if (flag && w && !last) throw No_solution();
      }
      last = w;
      if (w == 1) ++cnt;
      total += w > 0;
    }
    if (cnt > (type == 0 ? 2 : 1)) throw No_solution();
    cnt = 0;
    for (int i = 0; i < x->edge.size(); ++i) {
      int tmp = x->edge[i]->sum;
      if (tmp > 0 && tmp < x->edge[i]->size) {
        if (type == 1)
          x->edge[i] = solve(x->edge[i], 1);
        else if (type == 2)
          x->edge[i] = solve(x->edge[i], 2);
        else if (total == 1)
          x->edge[i] = solve(x->edge[i], 0);
        else {
          if (!cnt)
            x->edge[i] = solve(x->edge[i], 2);
          else
            x->edge[i] = solve(x->edge[i], 1);
        }
      }
      cnt += (tmp > 0);
    }
    return x;
  }
  Node* solve(Node* x, int type) {
    push_down(x);
    if (x->id) return x;
    if (x->PQ_type == 0)
      return P_operation(x, type);
    else
      return Q_operation(x, type);
  }

 public:
  PQ_tree(int size) : size(size), flag(1), data(new bool[size + 1]) { build(); }
  ~PQ_tree() {
    delete data;
    delete root;
  }
  PQ_tree(const PQ_tree& other)
      : size(other.size),
        flag(other.flag),
        root(new Node(*other.root)),
        data(new bool[size + 1]) {}
  PQ_tree& operator=(const PQ_tree& other) {
    if (this == &other) return *this;
    delete root;
    size = other.size;
    flag = other.flag;
    delete data;
    data = new bool[size + 1];
    root = new Node(*other.root);
    return *this;
  }
  void insert(std::vector<int> data_in) {
    if (!flag) return;
    for (int i = 1; i <= size; i++) {
      data[i] = 0;
    }
    for (int i = 0; i < data_in.size(); i++) {
      data[data_in[i]] = 1;
    }
    dfs(root);
    if (root->sum) {
      try {
        root = solve(root, 0);
      } catch (...) {
        flag = 0;
      }
    }
  }
  std::vector<int> print() {
    ans.clear();
    if (flag) get_ans(root);
    return ans;
  }
  void check(Node* x) {
    if (x->id)
      printf("%d", x->id);
    else
      printf("-%d", x->PQ_type);
    if (x->edge.size()) {
      printf("(");
      for (int i = 0; i < x->edge.size(); i++) {
        if (i) printf(",");
        check(x->edge[i]);
      }
      printf(")");
    }
  }
  void work() {
    check(root);
    puts("");
    puts("--------------------------");
  }
};
}  // namespace sjtu
char ch[1000][1000];
std::vector<int> vec;
int main() {
  int n;
  scanf("%d", &n);
  sjtu::PQ_tree t(n);
  for (int i = 1; i <= n; i++) {
    scanf("%s", ch[i] + 1);
    vec.clear();
    for (int j = 1; j <= n; j++)
      if (ch[i][j] == '1') vec.push_back(j);
    t.insert(vec);
  };
  vec = t.print();
  char ans[1000];
  if (vec.empty())
    puts("NO");
  else {
    puts("YES");
    for (int i = 1; i <= n; i++) {
      for (int j = 0; j < n; j++) ans[j] = ch[i][vec[j]];
      ans[n] = '\0';
      puts(ans);
    }
  }
}
