#include <bits/stdc++.h>
using namespace std;
const long long MOD = 1e9 + 7;
int n, m, par[2010], gx[2010][2010], ans[2010], num[2010], dg[2010];
string s[1010];
vector<int> g[2010], topo;
bool vis[2010];
int FIND(int pos) {
  if (par[pos] != pos) par[pos] = FIND(par[pos]);
  return par[pos];
}
void UNION(int pos1, int pos2) { par[FIND(pos1)] = FIND(pos2); }
void dfs(int pos) {
  if (vis[pos]) return;
  vis[pos] = true;
  for (int i = 0; i < g[pos].size(); i++) dfs(g[pos][i]);
  topo.push_back(pos);
}
int dfs2(int pos) {
  if (ans[pos] != 0) return ans[pos];
  int ret = 1;
  for (int i = 0; i < g[pos].size(); i++) ret = max(ret, dfs2(g[pos][i]) + 1);
  return ans[pos] = ret;
}
int main() {
  memset(gx, -1, sizeof(gx));
  for (int i = 0; i < 2005; i++) par[i] = i;
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    cin >> s[i];
    for (int j = 0; j < m; j++)
      if (s[i][j] == '=') UNION(i, j + n);
  }
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < m; j++) {
      int pos1 = FIND(i), pos2 = FIND(j + n);
      if (s[i][j] == '=') {
        if ((gx[pos1][pos2] != -1 && gx[pos1][pos2] != 2) ||
            (gx[pos2][pos1] != -1 && gx[pos2][pos1] != 2)) {
          puts("No");
          return 0;
        }
        gx[pos1][pos2] = gx[pos2][pos1] = 2;
        continue;
      }
      if (s[i][j] == '>') {
        if ((gx[pos1][pos2] != -1 && gx[pos1][pos2] != 0) ||
            (gx[pos2][pos1] != -1 && gx[pos2][pos1] != 1)) {
          puts("No");
          return 0;
        }
        if (gx[pos1][pos2] == -1 && pos1 != pos2)
          g[pos1].push_back(pos2), dg[pos2]++;
        gx[pos1][pos2] = 0;
        gx[pos2][pos1] = 1;
      } else {
        if ((gx[pos1][pos2] != -1 && gx[pos1][pos2] != 1) ||
            (gx[pos2][pos1] != -1 && gx[pos2][pos1] != 0)) {
          puts("No");
          return 0;
        }
        if (gx[pos2][pos1] == -1 && pos1 != pos2)
          g[pos2].push_back(pos1), dg[pos1]++;
        gx[pos1][pos2] = 1;
        gx[pos2][pos1] = 0;
      }
    }
  }
  int all = 0;
  for (int i = 0; i < m + n; i++)
    if (FIND(i) == i) all++;
  for (int i = 0; i < m + n; i++) {
    if (vis[FIND(i)] || dg[FIND(i)] > 0) continue;
    dfs(FIND(i));
  }
  if (topo.size() != all) {
    puts("No");
    return 0;
  }
  reverse(topo.begin(), topo.end());
  for (int i = 0; i < topo.size(); i++) num[topo[i]] = i;
  for (int i = 0; i < topo.size(); i++) {
    for (int j = 0; j < g[topo[i]].size(); j++) {
      if (num[g[topo[i]][j]] < num[topo[i]]) {
        puts("No");
        return 0;
      }
    }
  }
  for (int i = 0; i < m + n; i++) {
    if (ans[FIND(i)] != 0) continue;
    dfs2(FIND(i));
  }
  for (int i = 0; i < m + n; i++)
    if (ans[i] == 0) ans[i] = ans[FIND(i)];
  puts("Yes");
  for (int i = 0; i < n; i++) printf("%d ", ans[i]);
  cout << endl;
  for (int i = n; i < m + n; i++) printf("%d ", ans[i]);
  cout << endl;
  return 0;
}
