#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2005;
template <size_t N>
struct DSU {
  int parent[N];
  void init(int n) { iota(parent + 1, parent + n + 1, 1); }
  int find(int x) { return x == parent[x] ? x : parent[x] = find(parent[x]); }
  void merge(int x, int y) { parent[find(x)] = find(y); }
};
int n, m;
char g[MAXN][MAXN];
DSU<MAXN> dsu;
vector<int> edges[MAXN];
int vis[MAXN], deg[MAXN], value[MAXN];
bool dfs(int x) {
  if (vis[x] == 2) return true;
  if (vis[x] == 1) return false;
  vis[x] = 1;
  for (auto i : edges[x])
    if (!dfs(i)) return false;
  vis[x] = 2;
  return true;
}
bool check() {
  for (int i = 1; i <= n + m; i++)
    if (!vis[i] && !dfs(i)) return false;
  return true;
}
void bfs() {
  memset(vis, 0, sizeof vis);
  queue<int> q;
  for (int i = 1; i <= n + m; i++)
    if (i == dsu.find(i) && deg[i] == 0) {
      value[i] = 1;
      q.push(i);
    }
  while (!q.empty()) {
    int x = q.front();
    for (auto i : edges[x]) {
      value[i] = max(value[i], value[x] + 1);
      if (--deg[i] == 0) q.push(i);
    }
    q.pop();
  }
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= n; i++) scanf("%s", g[i] + 1);
  dsu.init(n + m);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
      if (g[i][j] == '=') dsu.merge(i, n + j);
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++) {
      if (g[i][j] == '<') {
        edges[dsu.find(i)].push_back(dsu.find(n + j));
        deg[dsu.find(n + j)]++;
      } else if (g[i][j] == '>') {
        edges[dsu.find(n + j)].push_back(dsu.find(i));
        deg[dsu.find(i)]++;
      }
    }
  if (!check()) {
    printf("No\n");
    return 0;
  }
  bfs();
  printf("Yes\n");
  for (int i = 1; i <= n; i++) printf("%d ", value[dsu.find(i)]);
  printf("\n");
  for (int i = 1; i <= m; i++) printf("%d ", value[dsu.find(n + i)]);
  printf("\n");
  return 0;
}
