//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 1;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish = process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish]; set<int> mE;
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}
        for (int j = idx+1; j < right; j++) if (s[process[j].second] != mS){cout<<"NO"<<endl; return 0;}

        set<int> dishNoEqual; vector<int> dishEqual;
        for (int j = idx; j < right; j++) {
            if (e[process[j].second].size() == 0){ dishNoEqual.insert(process[j].second);}
            else{dishEqual.push_back(process[j].second);}
        }
        if (dishEqual.size()>0) {
            for (int l = 0; l < dishEqual.size()-1; l++) if (e[dishEqual[l]] != e[dishEqual[l+1]]){cout<<"NO"<<endl; return 0;}
            mE = e[dishEqual[0]];
        }

        unsigned long amtInBetween = mS.size()-allAssigned.size();
        //Assign
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        if (amtInBetween> 0) counter++;

        for (auto d : dishNoEqual) {
            if (resN[d] == 0) resN[d] = counter;
        }
        if (dishNoEqual.size() > 0) counter++;

        for (int l = 0; l < dishEqual.size(); l++){
            int d = dishEqual[l];
            if (resN[d] == 0) resN[d] = counter;
        }
        for (auto d : mE){
            if (resM[d] == 0) resM[d] = counter;
           allAssigned.insert(d);
       }
        if (dishEqual.size()>0) counter++;

        idx = right;
    }
    int lastDish = process[process.size()-1].second;
    for(int i = 0; i < m; i++) if (s[lastDish].count(i)==0 && e[lastDish].count(i)==0) resM[i] = counter;

    cout<<"YES"<<endl;
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 0;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish = process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish]; set<int> mE = e[mainDish];
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}

        for (int j = idx+1; j < right; j++){
            int jDish = process[j].second;
            set<int> jS = s[jDish]; set<int> jE = e[jDish];
            if (mS != jS || mE != jE) {cout<<"NO"<<endl; return 0;}
        }

        unsigned long amtInBetween = mS.size()-allAssigned.size();
        //Assign
        counter++;
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }

        if (amtInBetween> 0) counter++;
        for (auto d : mE) {
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        for (int j = idx; j < right; j++) resN[process[j].second] = counter;

        idx = right;
    }
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 1;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish = process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish];
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}
        for (int j = idx+1; j < right; j++) if (s[process[j].second] != mS){cout<<"NO"<<endl; return 0;}

        set<int> dishNoEqual; vector<int> dishEqual;
        for (int j = idx; j < right; j++) {
            if (e[process[j].second].size() == 0){ dishNoEqual.insert(process[j].second);}
            else{dishEqual.push_back(process[j].second);}
        }
        if (dishEqual.size()>0) for (int l = 0; l < dishEqual.size()-1; l++) if (e[dishEqual[l]] != e[dishEqual[l+1]]){cout<<"NO"<<endl; return 0;}

        unsigned long amtInBetween = mS.size()-allAssigned.size();
        //Assign
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        if (amtInBetween> 0) counter++;

        for (auto d : dishNoEqual) {
            if (resN[d] == 0) resN[d] = counter;
            allAssigned.insert(d);
        }
        if (dishNoEqual.size() > 0) counter++;

        for (int l = 0; l < dishEqual.size(); l++){
            int d = dishEqual[l];
            if (resN[d] == 0) resN[d] = counter;
            for (auto d1 : e[d]) if (resM[d1] == 0) resM[d1] = counter;
            allAssigned.insert(d);
        }
        if (dishEqual.size()>0) counter++;

        idx = right;
    }
    int lastDish = process[process.size()-1].second;
    for(int i = 0; i < m; i++) if (s[lastDish].count(i)==0 && e[lastDish].count(i)==0) resM[i] = counter;

    cout<<"YES"<<endl;
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<vector<int>> s (n);
    vector<vector<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].push_back(j);
        if (c-'=' == 0) e[i].push_back(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 0;
    int amtMAssigned = 0;
    sort(process.begin(), process.end());
//    for (int t = 0; t < process.size(); t++) cout<<" t "<<process[t].first<<" "<<process[t].second<<endl;
    int idx = 0;
    while (idx < process.size()){
        int mainDish =process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;
//        cout<<" left right "<<idx<<" "<<right<<endl;

        set<int> mS; set<int> mE;

        //Check
        for (int k = 0; k < s[mainDish].size(); k++) mS.insert(s[mainDish][k]);
        auto amtEq = e[mainDish].size();
        for (int k = 0; k < e[mainDish].size(); k++) mE.insert(e[mainDish][k]);

        for (int j = idx+1; j < right; j++){
            int jDish = process[j].second;
            if (e[jDish].size() != amtEq){cout<<"NO"<<endl; return 0;}
            for (int k = 0; k < s[jDish].size(); k++) if (mS.count(s[jDish][k])  == 0){cout<<"NO"<<endl; return 0;}
            for (int k = 0; k < e[jDish].size(); k++) if (mE.count(e[jDish][k]) == 0){cout<<"NO"<<endl; return 0;}
        }

        counter++;
        int newCount = 0;
        //Assign
        for (int k = 0; k < s[mainDish].size(); k++){
            if (resM[s[mainDish][k]] == 0) newCount++;
            resM[s[mainDish][k]] = counter;
        }
        if (newCount !=  s[mainDish].size()-amtMAssigned){cout<<"NO"<<endl; return 0;}

        if (s[mainDish].size()> 0) counter ++;
        for (int k = 0; k < e[mainDish].size(); k++){
            if (resM[e[mainDish][k]] != 0){cout<<"NO"<<endl; return 0;}
            resM[e[mainDish][k]] = counter;
        }

        for (int j = idx; j < right; j++) resN[process[j].second] = counter;

        amtMAssigned +=s[mainDish].size()+e[mainDish].size();
        idx = right;
    }
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
using namespace std;
int n, m, r[2005], in[2005];
vector<int> to[2005];
char l[1005][1005];
int fa[2005]; int find(int x){return fa[x] == x?x:find(fa[x]);}

void add(int x, int y){
    to[x].push_back(y);
    in[y]++;
}

void dfs(int x){
    in[x]--;
    r[x]++;
    for (auto i : to[x]){
        if (r[i] < r[x]) r[i] = r[x];
        if (!--in[i]) dfs(i);
    }
}

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    for (int i = 0; i < n+m; i++) fa[i] = i;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >> l[i][j];
        if (l[i][j] == '=') fa[find(i)] = find(n+j);
    }
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        if (l[i][j] == '<') add(find(i), find(n+j));
        if (l[i][j] == '>') add(find(n+j), find(i));
    }
    for (int i = 0; i < n+m; i++) if (find(i) == i && !in[i]) dfs(i);
    for (int i = 0; i < n+m; i++) if (find(i) == i && in[i] > 0) {cout<<"NO\n"; return 0; }

    cout<<"Yes"<<endl;
    for (int i = 0; i < n; i++) cout<<r[find(i)]<<(i==n-1 ? "\n":" ");
    for (int i = 0; i < m; i++) cout<<r[find(n+i)]<<(i==m-1 ? "\n":" ");

    return 0;
}


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 0;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish = process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish]; set<int> mE = e[mainDish];
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}

        for (int j = idx+1; j < right; j++){
            int jDish = process[j].second;
            set<int> jS = s[jDish]; set<int> jE = e[jDish];
            if (mS != jS || mE != jE) {cout<<"NO"<<endl; return 0;}
        }

        unsigned long amtInBetween = mS.size()-allAssigned.size();
        //Assign
        counter++;
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }

        if (amtInBetween> 0) counter++;
        for (auto d : mE) {
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        for (int j = idx; j < right; j++) resN[process[j].second] = counter;

        idx = right;
    }
    cout<<"YES"<<endl;
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
using namespace std;
int n, m, in[2005], f[2005];
char l[1005][1005];
vector<int> to[2005];
int fa[2005]; int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}

void add(int x, int y){
    to[x].push_back(y);
    in[y]++;
}

void dfs(int x){
    in[x]-=1;
    f[x]++;
    for (auto i : to[x]){
        if (f[x] > f[i]) f[i] = f[x];
        if (!--in[i]) dfs(i);
    }
}

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    for (int i = 0; i < n+m; i++) fa[i] = i;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >> l[i][j];
        if (l[i][j] == '=') fa[find(i)] = find(n+j);
    }
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        if (l[i][j] == '<') add(find(i), find(n+j));
        if (l[i][j] == '>') add(find(n+j), find(i));
    }
    for (int i = 0; i < n+m; i++) if (find(i) == i && !in[i]) dfs(i);
    for (int i = 0; i < n+m; i++) if (find(i) == i && in[i] > 0 ) {cout<<"NO \n"; return 0;}
    cout<<"YES \n";
    for (int i = 0; i < n; i++) cout<<f[find(i)]<<(i == n-1? "\n" :" ");
    for (int i = 0; i < m; i++) cout<<f[find(i+n)]<<(i == m-1? "\n" :" ");

    return 0;
}


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
using namespace std;
int n, m, r[2005], in[2005];
vector<int> to[2005];
char l[1005][1005];
int fa[2005]; int find(int x){return fa[x] == x?x:find(fa[x]);}

void add(int x, int y){
    to[x].push_back(y);
    in[y]++;
}

void dfs(int x){
    in[x]--;
    r[x]++;
    for (auto i : to[x]){
        if (r[i] < r[x]) r[x] = r[x];
        if (!--in[i]) dfs(i);
    }
}

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    for (int i = 0; i < n+m; i++) fa[i] = i;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >> l[i][j];
        if (l[i][j] == '=') fa[find(i)] = find(n+j);
    }
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        if (l[i][j] == '<') add(find(i), find(n+j));
        if (l[i][j] == '>') add(find(n+j), find(i));
    }
    for (int i = 0; i < n+m; i++) if (in[i] == 0) dfs(i);
    for (int i = 0; i < n+m; i++) if (in[i] != 0) {cout<<"NO\n"; return 0; }

    for (int i = 0; i < n; i++) cout<<r[i]<<(i==n-1 ? "\n":" ");
    for (int i = 0; i < m; i++) cout<<r[n+i]<<(i==m-1 ? "\n":" ");

    return 0;
}


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
using namespace std;
int n, m, r[2005], in[2005];
vector<int> to[2005];
char l[1005][1005];
int fa[2005]; int find(int x){return fa[x] == x?x:find(fa[x]);}

void add(int x, int y){
    to[x].push_back(y);
    in[y]++;
}

void dfs(int x){
    in[x]--;
    r[x]++;
    for (auto i : to[x]){
        if (r[i] < r[x]) r[x] = r[x];
        if (!--in[i]) dfs(i);
    }
}

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    for (int i = 0; i < n+m; i++) fa[i] = i;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >> l[i][j];
        if (l[i][j] == '=') fa[find(i)] = find(n+j);
    }
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        if (l[i][j] == '<') add(find(i), find(n+j));
        if (l[i][j] == '>') add(find(n+j), find(i));
    }
    for (int i = 0; i < n+m; i++) if (in[i] == 0) dfs(i);
    for (int i = 0; i < n+m; i++) if (in[i] != 0) {cout<<"NO\n"; return 0; }

    cout<<"Yes"<<endl;
    for (int i = 0; i < n; i++) cout<<r[i]<<(i==n-1 ? "\n":" ");
    for (int i = 0; i < m; i++) cout<<r[n+i]<<(i==m-1 ? "\n":" ");

    return 0;
}


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 0;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish = process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish]; set<int> mE = e[mainDish];
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}

        for (int j = idx+1; j < right; j++){
            int jDish = process[j].second;
            set<int> jS = s[jDish]; set<int> jE = e[jDish];
            if (mS != jS || mE != jE) {cout<<"NO"<<endl; return 0;}
        }

        //Assign
        counter++;
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }

        if (mS.size()-allAssigned.size()> 0) counter ++;
        for (auto d : mE) {
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        for (int j = idx; j < right; j++) resN[process[j].second] = counter;

        idx = right;
    }
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
using namespace std;
int n, m, r[2005], in[2005];
vector<int> to[2005];
char l[1005][1005];
int fa[2005]; int find(int x){return fa[x] == x?x:find(fa[x]);}

void add(int x, int y){
    to[x].push_back(y);
    in[y]++;
}

void dfs(int x){
    in[x]--;
    r[x]++;
    for (auto i : to[x]){
        if (r[i] < r[x]) r[i] = r[x];
        if (!--in[i]) dfs(i);
    }
}

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    for (int i = 0; i < n+m; i++) fa[i] = i;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >> l[i][j];
        if (l[i][j] == '=') fa[find(i)] = find(n+j);
    }
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        if (l[i][j] == '<') add(find(i), find(n+j));
        if (l[i][j] == '>') add(find(n+j), find(i));
    }
    for (int i = 0; i < n+m; i++) if (in[i] == 0) dfs(i);
    for (int i = 0; i < n+m; i++) if (in[i] != 0) {cout<<"NO\n"; return 0; }

    cout<<"Yes"<<endl;
    for (int i = 0; i < n; i++) cout<<r[i]<<(i==n-1 ? "\n":" ");
    for (int i = 0; i < m; i++) cout<<r[n+i]<<(i==m-1 ? "\n":" ");

    return 0;
}


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 0;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish = process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish]; set<int> mE = e[mainDish];
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}

        for (int j = idx+1; j < right; j++){
            int jDish = process[j].second;
            set<int> jS = s[jDish]; set<int> jE = e[jDish];
            if (mS != jS || mE != jE) {cout<<"NO"<<endl; return 0;}
        }

        unsigned long amtInBetween = mS.size()-allAssigned.size();
        //Assign
        counter++;
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }

        if (amtInBetween> 0) counter++;
        for (auto d : mE) {
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        for (int j = idx; j < right; j++) resN[process[j].second] = counter;

        idx = right;
    }
    counter++;
    int lastDish = process[process.size()-1].second;
    for(int i = 0; i < m; i++) if (s[lastDish].count(i)==0 && e[lastDish].count(i)==0) resM[i] = counter;

    cout<<"YES"<<endl;
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


//
//  main.cpp
//  GourmetChoice
//
//  Created by Cynthia Du on 3/21/20.
//  Copyright © 2020 Cynthia Du. All rights reserved.
//

#include <bits/stdc++.h>
#include <iostream>
using namespace std;
int n, m;
int resN[1005], resM[1005];
char c;

int main(int argc, const char * argv[]) {
    cin >> n >> m;
    vector<set<int>> s (n);
    vector<set<int>> e (n);

    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++){
        cin >>c;
        if (c-'>'== 0) s[i].insert(j);
        if (c-'=' == 0) e[i].insert(j);
    }
    vector<pair<int, int>> process;
    for (int i = 0; i < n; i++){
        process.push_back(make_pair(s[i].size(), i));
    }
    int counter = 0;
    sort(process.begin(), process.end());
    set<int> allAssigned;
    int idx = 0;
    while (idx < process.size()){
        int mainDish =process[idx].second;
        int right = idx;
        while (right < process.size() && process[right].first == process[idx].first) right++;

        //Check
        set<int> mS = s[mainDish]; set<int> mE = e[mainDish];
        if (!includes(mS.begin(), mS.end(), allAssigned.begin(), allAssigned.end())) {cout<<"NO"<<endl; return 0;}

        for (int j = idx+1; j < right; j++){
            int jDish = process[j].second;
            set<int> jS = s[jDish]; set<int> jE = e[jDish];
            if (mS != jS || mE != jE) {cout<<"NO"<<endl; return 0;}
        }

        //Assign
        counter++;
        for (auto d : mS){
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }

        if (s[mainDish].size()> 0) counter ++;
        for (auto d : mE) {
            if (resM[d] == 0) resM[d] = counter;
            allAssigned.insert(d);
        }
        for (int j = idx; j < right; j++) resN[process[j].second] = counter;

        idx = right;
    }
    cout<<resN[0];
    for (int i = 1; i < n; i++) cout<<" "<<resN[i];
    cout<<endl;
    cout<<resM[0];
    for (int i = 1; i < m; i++) cout<<" "<<resM[i];
    cout<<endl;

    return 0;
}

//Notes:
//1. Used vector instead of set; so had to laboriously check, code was awful


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    vvec<int> G(N+M);
    // 入次数を管理する
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
            cnt[uni.root(i)]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
            cnt[uni.root(N+j)]++;
        }
    }
    vec<int> ans(N+M, -1);
    queue<int> q;
    rep(i,N+M){
        if(uni.root(i) != i)continue;
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    rep(i,N+M){
        ans[i] = ans[uni.root(i)];
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(ans[i] == -1 || ans[N+j] == -1)ok = false;
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        //if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        //if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};

ll N, M;
vvec<int> G;
vec<ll> v;
vec<bool> visited;
bool dfs(int cur, int pre = -1, ll cnt = 1){
    //visited[cur] = true;
    chmax(v[cur],cnt);
    bool ng = false;
    for(auto &nxt: G[cur]){
        // ループ
        if(visited[nxt]){
            ng = true;
            continue;
        }
        visited[cur] = true;
        ng |= dfs(nxt, cur, cnt+1);
    }
    return ng;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    cin >> N >> M;
    vector<string> a(N);
    rep(i,N){
        cin >> a[i];
    }
    UnionFind uni(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '='){
            uni.unite(i, N + j);
        }
    }
    G.resize(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '=')continue;
        if(a[i][j] == '>'){
            G[uni.Parent[N + j]].push_back(uni.Parent[i]);
        }
        if(a[i][j] == '<'){
            G[uni.Parent[i]].push_back(uni.Parent[N + j]);
        }
    }

    //rep(i,N+M)print(G[i]);
    v.resize(N+M);
    bool ok = true;
    rep(i,N+M){
        //if(G[i].empty())continue;
        visited.assign(N+M, false);
        if(dfs(i)){
            //dump(i);
            ok = false;
        }
    }
    if(!ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        if(v[i] == 0){
            v[i] = v[uni.Parent[i]] ;
        }
        cout << v[i] << " ";
    }
    cout << endl;
    rep(j,M){
        if(v[N+j] == 0){
            v[N+j] = v[uni.Parent[N+j]];
        }
        cout << v[N+j] <<  " ";
    }
    cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
#define uniq(x) x.erase(unique(all(x)),x.end())
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};

ll N, M;
vvec<int> G;
vec<ll> v;
vec<bool> visited;
bool dfs(int cur, int pre = -1, ll cnt = 1){
    //visited[cur] = true;
    chmax(v[cur],cnt);
    bool ng = false;
    for(auto &nxt: G[cur]){
        // ループ
        if(visited[nxt]){
            ng = true;
            continue;
        }
        visited[cur] = true;
        ng |= dfs(nxt, cur, v[cur]+1);
    }
    return ng;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    cin >> N >> M;
    vector<string> a(N);
    rep(i,N){
        cin >> a[i];
    }
    UnionFind uni(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '='){
            uni.unite(i, N + j);
        }
    }
    G.resize(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '=')continue;
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
        }
    }
    v.assign(N+M,-1);
    bool ok = true;
    rep(i,N+M){
        //if(G[i].empty())continue;
        visited.assign(N+M, false);
        if(dfs(i)){
            //dump(i);
            ok = false;
        }
    }
    if(!ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << v[uni.root(i)] << " ";
    }
    cout << endl;
    rep(j,M){
        cout << v[uni.root(N+j)] <<  " ";
    }
    cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
#define uniq(x) x.erase(unique(all(x)),x.end())
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};

ll N, M;
vvec<int> G;
vec<ll> v;
vec<bool> visited;
bool dfs(int cur, int pre = -1, ll cnt = 1){
    //visited[cur] = true;
    chmax(v[cur],cnt);
    bool ng = false;
    for(auto &nxt: G[cur]){
        // ループ
        if(visited[nxt]){
            ng = true;
            return true;
        }
        visited[cur] = true;
        ng |= dfs(nxt, cur, v[cur]+1);
    }
    return ng;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    cin >> N >> M;
    vector<string> a(N);
    rep(i,N){
        cin >> a[i];
    }
    UnionFind uni(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '='){
            uni.unite(i, N + j);
        }
    }
    G.resize(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '=')continue;
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
        }
    }
    v.assign(N+M,-1);
    bool ok = true;
    rep(i,N+M){
        //if(G[i].empty())continue;
        visited.assign(N+M, false);
        if(dfs(i)){
            //dump(i);
            ok = false;
        }
    }
    if(!ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << v[uni.root(i)] << " ";
    }
    cout << endl;
    rep(j,M){
        cout << v[uni.root(N+j)] <<  " ";
    }
    cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};

ll N, M;
vvec<int> G;
vec<ll> v;
vec<bool> visited;
bool dfs(int cur, int pre = -1, ll cnt = 1){
    //visited[cur] = true;
    chmax(v[cur],cnt);
    bool ng = false;
    for(auto &nxt: G[cur]){
        // ループ
        if(visited[nxt]){
            ng = true;
            continue;
        }
        visited[cur] = true;
        ng |= dfs(nxt, cur, cnt+1);
    }
    return ng;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    cin >> N >> M;
    vector<string> a(N);
    rep(i,N){
        cin >> a[i];
    }
    UnionFind uni(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '='){
            uni.unite(i, N + j);
        }
    }
    G.resize(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '=')continue;
        if(a[i][j] == '>'){
            G[uni.Parent[N + j]].push_back(uni.Parent[i]);
        }
        if(a[i][j] == '<'){
            G[uni.Parent[i]].push_back(uni.Parent[N + j]);
        }
    }

    //rep(i,N+M)print(G[i]);
    v.resize(N+M);
    bool ok = true;
    rep(i,N+M){
        //if(G[i].empty())continue;
        visited.assign(N+M, false);
        if(dfs(i)){
            //dump(i);
            ok = false;
        }
    }
    if(!ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << v[uni.Parent[i]] << " ";
    }
    cout << endl;
    rep(j,M){
        cout << v[uni.Parent[N + j]] <<  " ";
    }
    cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    vvec<int> G(N+M);
    // 入次数を管理する
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
            cnt[i]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
            cnt[N+j]++;
        }
    }
    vec<int> ans(N+M, -1);
    queue<int> q;
    rep(i,N+M){
        if(uni.root(i) != i)continue;
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    rep(i,N+M){
        ans[i] = ans[uni.root(i)];
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(a[i][j] == -1)ok = false;
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    vvec<int> G(N+M);
    // 入次数を管理する
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(i);
            cnt[i]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(N+j);
            cnt[N+j]++;
        }
    }
    vec<int> ans(N+M, -1);
    queue<int> q;
    rep(i,N+M){
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(a[i][j] == -1)ok = false;
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};

ll N, M;
vvec<int> G;
vec<ll> v;
vec<bool> visited;
bool dfs(int cur, int pre = -1, ll cnt = 1){
    //visited[cur] = true;
    chmax(v[cur],cnt);
    bool ng = false;
    for(auto &nxt: G[cur]){
        // ループ
        if(visited[nxt]){
            ng = true;
            continue;
        }
        visited[cur] = true;
        ng |= dfs(nxt, cur, cnt+1);
    }
    return ng;
}
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);

    cin >> N >> M;
    vector<string> a(N);
    rep(i,N){
        cin >> a[i];
    }
    UnionFind uni(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '='){
            uni.unite(i, N + j);
        }
    }
    G.resize(N+M);
    rep(i,N)rep(j,M){
        if(a[i][j] == '=')continue;
        if(a[i][j] == '>'){
            G[uni.Parent[N + j]].push_back(uni.Parent[i]);
        }
        if(a[i][j] == '<'){
            G[uni.Parent[i]].push_back(uni.Parent[N + j]);
        }
    }

    //rep(i,N+M)print(G[i]);
    v.assign(N+M,-1);
    bool ok = true;
    rep(i,N+M){
        //if(G[i].empty())continue;
        visited.assign(N+M, false);
        if(dfs(i)){
            //dump(i);
            ok = false;
        }
    }
    if(!ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        if(v[i] == -1){
            v[i] = v[uni.Parent[i]] ;
        }
        cout << v[i] << " ";
    }
    cout << endl;
    rep(j,M){
        if(v[N+j] == -1){
            v[N+j] = v[uni.Parent[N+j]];
        }
        cout << v[N+j] <<  " ";
    }
    cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    vvec<int> G(N+M);
    // 入次数を管理する
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
            cnt[uni.root(i)]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
            cnt[uni.root(N+j)]++;
        }
    }
    vec<int> ans(N+M, -1);
    queue<int> q;
    rep(i,N+M){
        if(uni.root(i) != i)continue;
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    rep(i,N+M){
        ans[i] = ans[uni.root(i)];
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(ans[i] == -1 || ans[N+j] == -1)ok = false;
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    vvec<int> G(N+M);
    // 入次数を管理する
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
            cnt[uni.root(i)]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
            cnt[uni.root(N+j)]++;
        }
    }
    vec<int> ans(N+M, -1);
    queue<int> q;
    rep(i,N+M){
        if(uni.root(i) != i)continue;
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    rep(i,N+M){
        ans[i] = ans[uni.root(i)];
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(a[i][j] == -1)ok = false;
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    // 入次数を管理する
    vvec<int> G(N+M);
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(i);
            cnt[i]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(N+j);
            cnt[N+j]++;
        }
    }
    vec<int> ans(N+M, -1);

    queue<int> q;
    rep(i,N+M){
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i,N) for(int i=0;i<int(N);++i)
#define rep1(i,N) for(int i=1;i<int(N);++i)
#define all(a) (a).begin(),(a).end()
#define print(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<_<<", "; cerr<<"]"<<endl; }
#define printpair(v) { cerr<<#v<<": [ "; for(auto _ : v) cerr<<"{"<<_.first<<","<<_.second<<"}"<<", "; cerr<<"]"<<endl; }
#define dump(x) cerr<<#x<<": "<<x<<endl;
#define bit(k) (1LL<<(k))
typedef long long ll;
typedef pair<int, int> i_i;
typedef pair<ll, ll> l_l;
template <class T> using vec = vector<T>;
template <class T> using vvec = vector<vec<T>>;
template< typename T1, typename T2 >
ostream &operator<<(ostream &os, const pair< T1, T2 >& p) {
  os << "{" <<p.first << ", " << p.second << "}";
  return os;
}
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

const int INF = (ll)1e9;
const ll INFLL = (ll)1e18+1;
const ll MOD = (ll)1e9+7;
const double PI = acos(-1.0);
/*
const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
const string dir = "DRUL";
*/

struct UnionFind{
    int n;
    vector<int> Parent;
    vector<int> sizes;
    UnionFind(int _n):n(_n),Parent(_n),sizes(_n,1){ rep(i,n)Parent[i]=i; }
    //find the root of x
    int root(int x){
        if(x!=Parent[x]){
        Parent[x] = root(Parent[x]);
        }
        return Parent[x];
    }
    //merge x and y
    void unite(int x,int y){
        x = root(x);
        y = root(y);
        if(x == y) return;
        if(sizes[x] < sizes[y]) swap(x, y);
        Parent[y] = x;
        sizes[x] += sizes[y];
    }
    bool same(int x,int y){ return root(x) == root(y); }
    int size(int x){ return sizes[root(x)]; }
    int group_num(){
        set<int> s;
        for(int i = 0; i < n; ++i){
            s.insert(root(i));
        }
        return int(s.size());
    }
};
int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M;
    cin >> N >> M;
    vector<string> a(N);
    rep(i,N)cin >> a[i];
    UnionFind uni(N+M);
    rep(i,N){
        rep(j,M){
            if(a[i][j] == '='){
                uni.unite(i, N+j);
            }
        }
    }
    vvec<int> G(N+M);
    // 入次数を管理する
    vec<int> cnt(N+M,0);
    rep(i,N)rep(j,M){
        if(a[i][j] == '>'){
            G[uni.root(N+j)].push_back(uni.root(i));
            cnt[uni.root(i)]++;
        }
        if(a[i][j] == '<'){
            G[uni.root(i)].push_back(uni.root(N+j));
            cnt[uni.root(N+j)]++;
        }
    }
    vec<int> ans(N+M, -1);
    queue<int> q;
    rep(i,N+M){
        if(uni.root(i) != i)continue;
        if(cnt[i] == 0){
            q.push(i);
            ans[i] = 1;
        }
    }
    while(not q.empty()){
        int cur = q.front();
        q.pop();
        for(auto &nxt: G[cur]){
            chmax(ans[nxt], ans[cur]+1);
            cnt[nxt]--;
            if(cnt[nxt] == 0){
                q.push(nxt);
            }
        }
    }
    rep(i,N+M){
        ans[i] = ans[uni.root(i)];
    }
    bool ok = true;
    rep(i,N)rep(j,M){
        if(a[i][j] == -1)ok = false;
        if(a[i][j] == '=' && ans[i] != ans[N+j])ok = false;
        //if(a[i][j] == '>' && ans[i] <= ans[N+j])ok = false;
        //if(a[i][j] == '<' && ans[i] >= ans[N+j])ok = false;
    }
    if(not ok){
        cout << "No" << endl;
        return 0;
    }
    cout << "Yes" << endl;
    rep(i,N){
        cout << ans[i] << ((i == N-1) ? '\n': ' ');
    }
    rep(j,M){
        cout << ans[N+j] << ((j == M-1) ? '\n': ' ');
    }
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=2010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;
        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u,int c){
    nums[u] = max(nums[u],c);
    dfs_num[u] = VISITED;
    for(auto v : g[u]){
        //if(dfs_num[v]==VISITED) continue;
        dfs_2(v,c+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') g[ri].push_back(rj);
            if(s[j]=='>') g[rj].push_back(ri);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        int ri = root(i);
        if(dfs_num[ri]==UNVISITED)
        dfs(ri);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    dfs_num.assign(N+1,UNVISITED);
    nums.assign(N+1,-1);
    for (auto it =  st.rbegin();it!=st.rend();it++) {
            cout<<*it<<" ";
            if(dfs_num[*it]==UNVISITED)
            dfs_2(*it,1);
    }

    cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=1010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;

        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u,int c){
    nums[u] = nums[root(u)] = max(nums[root(u)],c);
    //cout<<u<<" "<<root(u)<<" "<<c<<endl;
    for(auto v : g[u]){
        dfs_2(v,c+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') g[ri].push_back(rj);
            if(s[j]=='>') g[rj].push_back(ri);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        if(dfs_num[i]==UNVISITED)
        dfs(i);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    dfs_num.assign(N+1,-1);
    nums.assign(N+1,-1);
    for(auto it = st.rbegin();it!=st.rend();it++){
        //cout<<*it<<" ";
        if(dfs_num[*it]==-1)
        dfs_2(*it,1);
    }
    //cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=2010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;

        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u,int c){
    nums[u] = max(nums[u],c);
    dfs_num[u] = VISITED;
    for(auto v : g[u]){
        if(dfs_num[v]==VISITED) continue;
        dfs_2(v,c+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') g[ri].push_back(rj);
            if(s[j]=='>') g[rj].push_back(ri);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        int ri = root(i);
        if(dfs_num[ri]==UNVISITED)
        dfs(ri);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    dfs_num.assign(N+1,UNVISITED);
    nums.assign(N+1,-1);
    for (auto it =  st.rbegin();it!=st.rend();it++) {
            //cout<<*it<<" ";
            if(dfs_num[*it]==UNVISITED)
            dfs_2(*it,1);
    }

    //cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=2010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;

        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u,int c){
    nums[u] = max(nums[u],c);
    for(auto v : g[u]){
        dfs_2(v,c+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') g[ri].push_back(rj);
            if(s[j]=='>') g[rj].push_back(ri);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        int ri = root(i);
        if(dfs_num[ri]==UNVISITED)
        dfs(ri);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    nums.assign(N+1,-1);
    for (auto it =  st.rbegin();it!=st.rend();it++) {

            //cout<<*it<<" ";
            if(nums[*it]==-1)
            dfs_2(*it,1);
    }

    //cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=2010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;

        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u,int c){
    nums[u] = nums[root(u)] = max(nums[root(u)],c);
    for(auto v : g[u]){
        dfs_2(v,c+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') g[ri].push_back(rj);
            if(s[j]=='>') g[rj].push_back(ri);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        int ri = root(i);
        if(dfs_num[ri]==UNVISITED)
        dfs(ri);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    dfs_num.assign(N+1,-1);
    nums.assign(N+1,-1);
    for (auto it =  st.rbegin();it!=st.rend();it++) {
            //cout<<*it<<" ";
            dfs_2(*st.rbegin(),1);
    }

    //cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=2010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],reg[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;
        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u){
    nums[u] = 1;
    dfs_num[u] = VISITED;
    for(auto v : reg[u]){
        nums[u] = max(nums[u],nums[v]+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') {
                g[ri].push_back(rj);
                reg[rj].push_back(ri);
            }
            if(s[j]=='>') {
                g[rj].push_back(ri);
                reg[ri].push_back(rj);
            }
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        int ri = root(i);
        if(dfs_num[ri]==UNVISITED)
        dfs(ri);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    reverse(st.begin(),st.end()); st.push_back(-1);
    dfs_num.assign(N+1,UNVISITED);
    nums.assign(N+1,-1);
    for (int i  = 0;i<_sz(st)-1;i++) {
            //cout<<st[i]<<" ";
            if(dfs_num[st[i]]==UNVISITED)
            dfs_2(st[i]);
    }

   //cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define mkp(i,j) make_pair(i,j)
#define _sz(x) (int)x.size()

const int MAX=2010;;
typedef pair <int,int> ii;
typedef long long ll;
typedef vector < int > vi;
const int VISITED = 1;
const int UNVISITED = -1;
const int EXPLORED = 0;

vi g[MAX],dfs_num,st,nums;
int p[MAX],n,m,N;
bool loop;
char mp[MAX][MAX];

int root(int u){
    if(p[u]==u) return u;
    return p[u] = root(p[u]);
}

void join(int u,int v){
    int ru = root(u),rv = root(v);
    if(ru==rv) return ;
    p[rv] = ru;
}

void dfs(int u){
    dfs_num[u]=EXPLORED;
    for(auto v : g[u]){
        if(dfs_num[v]==EXPLORED) {
            loop = true; return;
        }
        if(dfs_num[v]==VISITED) continue;

        dfs(v);
    }
    dfs_num[u] = VISITED;
    st.push_back(u);
}

void dfs_2(int u,int c){
    nums[u] = nums[root(u)] = max(nums[root(u)],c);
    //cout<<u<<" "<<root(u)<<" "<<c<<endl;
    for(auto v : g[u]){
        dfs_2(v,c+1);
    }

}

void input(){

    for(int i = 0;i<n;i++){
        cin>>mp[i];
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            if(s[j]=='=') join(i,n+j);
        }
    }
    for(int i = 0;i<n;i++){
        string s;
        s = mp[i];
        for(int j = 0;j<m;j++){
            int ri = root(i); int rj = root(n+j);
            if(s[j]=='<') g[ri].push_back(rj);
            if(s[j]=='>') g[rj].push_back(ri);
        }
    }
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    loop = false;
    cin>>n>>m;
    N = m + n;
    dfs_num.assign(N+1,UNVISITED);
    for(int i = 0;i<=N;i++) p[i]=i;

    input();

    /*for(int j = 0;j<=N;j++){
        cout<<j<<":  ";
        for(int i : g[j]) cout<<i<<" ";
        cout<<endl;
    }*/

    for(int i = 0;i<N;i++){
        if(dfs_num[i]==UNVISITED)
        dfs(i);
    }

    if(loop) return cout<<"No\n" , 0;
    cout<<"Yes\n";

    dfs_num.assign(N+1,-1);
    nums.assign(N+1,-1);
    for(auto it = st.rbegin();it!=st.rend();it++){
        //cout<<*it<<" ";
        if(dfs_num[*it]==-1)
        dfs_2(*it,1);
    }
    //cout<<endl;
    int i;
    for(i = 0;i<n;i++) cout<<nums[root(i)]<<" "; cout<<endl;
    for(;i<N;i++) cout<<nums[root(i)]<<" "; cout<<endl;

    return 0;
}


/// IN THE NAME OF METAL
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}

const ll MAXN = 2e3 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7;
ll n, m, ans[MAXN], par[MAXN], Sz[MAXN], mark[MAXN], deg[MAXN];
vector<ll> adj[MAXN];
char A[MAXN][MAXN];

ll Find(ll v) {
    return par[v] == -1 ? v : par[v] = Find(par[v]);
}

ll Union(ll u,ll v) {
    u = Find(u), v = Find(v);
    if (u == v) return 0;
    if (Sz[v] < Sz[u]) swap(u, v);
    par[u] = v;
    Sz[v] += Sz[u];
    return 1;
}

void DFS(ll v, ll id) {
    mark[v] = 1;
    ans[v] = id;
    for (ll u : adj[v]) {
        if (mark[u]) continue;
        DFS(u, id + 1);
    }
}

ll Topo() {
    queue<ll> Q;
    vector<ll> ts;
    for (ll i = 1; i <= n + m; i++) {
        if (deg[i] == 0) Q.push(i), ans[i] = 1;
    }
    while (sz(Q)) {
        ll v = Q.front();
        Q.pop();
        ts.push_back(v);
        for (ll u : adj[v]) {
            deg[u]--;
            if (deg[u] == 0) Q.push(u), ans[u] = ans[v] + 1;
        }
    }
    return sz(ts) != n + m;
}

int main() {
    fill(par, par + MAXN, -1);
    fill(Sz, Sz + MAXN, 1);
    scanf("%lld%lld", &n, &m);
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            cin >> A[i][j];
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') Union(i, n + j);
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') continue;
            if (Find(i) == Find(n + j)) return !printf("No\n");
            if (A[i][j] == '<') adj[Find(i)].push_back(Find(j + n)), deg[j + n]++;
            if (A[i][j] == '>') adj[Find(j + n)].push_back(Find(i)), deg[i]++;
        }
    }
    if (Topo()) return !printf("No\n");
    printf("Yes\n");
    for (ll i = 1; i <= n + m; i++) {
        printf("%lld ", ans[Find(i)]);
        if (i == n) printf("\n");
    }
    return 0;
}


/// IN THE NAME OF METAL
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}

const ll MAXN = 5e3 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7;
ll n, m, ans[MAXN], par[MAXN], Sz[MAXN], mark[MAXN], deg[MAXN];
vector<ll> adj[MAXN];
char A[MAXN][MAXN];

ll Find(ll v) {
    return par[v] == -1 ? v : par[v] = Find(par[v]);
}

ll Union(ll u, ll v) {
    u = Find(u), v = Find(v);
    if (u == v) return 0;
    if (Sz[v] < Sz[u]) swap(u, v);
    par[u] = v;
    Sz[v] += Sz[u];
    return 1;
}

void DFS(ll v, ll id) {
    mark[v] = 1;
    ans[v] = id;
    for (ll u : adj[v]) {
        if (mark[u]) continue;
        DFS(u, id + 1);
    }
}

ll Topo() {
    queue<ll> Q;
    vector<ll> ts;
    ll cnt = 0;
    for (ll i = 1; i <= n + m; i++) {
        if (i == Find(i)) cnt++;
        if (deg[i] == 0 && (i == Find(i))) Q.push(i), ans[i] = 1;
    }
    while (sz(Q)) {
        ll v = Q.front();
        Q.pop();
        ts.push_back(v);
        for (ll u : adj[v]) {
            deg[u]--;
            if (deg[u] == 0) Q.push(u), ans[u] = ans[v] + 1;
        }
    }
    return sz(ts) != cnt;
}

int main() {
    fill(par, par + MAXN, -1);
    fill(Sz, Sz + MAXN, 1);
    scanf("%lld%lld", &n, &m);
    for (ll i = 1; i <= n; i++) {
        scanf("%s", A[i] + 1);
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') Union(i, n + j);
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') continue;
            if (Find(i) == Find(n + j)) return !printf("No\n");
            if (A[i][j] == '<') adj[Find(i)].push_back(Find(j + n)), deg[Find(j + n)]++;
            if (A[i][j] == '>') adj[Find(j + n)].push_back(Find(i)), deg[Find(i)]++;
        }
    }
    if (Topo()) return !printf("No\n");
    printf("Yes\n");
    for (ll i = 1; i <= n + m; i++) {
        printf("%lld ", ans[Find(i)]);
        if (i == n) printf("\n");
    }
    return 0;
}


/// IN THE NAME OF METAL
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}

const ll MAXN = 5e3 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7;
ll n, m, ans[MAXN], par[MAXN], Sz[MAXN], mark[MAXN], deg[MAXN];
vector<ll> adj[MAXN];
char A[MAXN][MAXN];

ll Find(ll v) {
    return par[v] == -1 ? v : par[v] = Find(par[v]);
}

ll Union(ll u,ll v) {
    u = Find(u), v = Find(v);
    if (u == v) return 0;
    if (Sz[v] < Sz[u]) swap(u, v);
    par[u] = v;
    Sz[v] += Sz[u];
    return 1;
}

void DFS(ll v, ll id) {
    mark[v] = 1;
    ans[v] = id;
    for (ll u : adj[v]) {
        if (mark[u]) continue;
        DFS(u, id + 1);
    }
}

ll Topo() {
    queue<ll> Q;
    vector<ll> ts;
    for (ll i = 1; i <= n + m; i++) {
        if (deg[i] == 0 && i == Find(i)) Q.push(i), ans[i] = 1;
    }
    while (sz(Q)) {
        ll v = Q.front();
        Q.pop();
        ts.push_back(v);
        for (ll u : adj[v]) {
            deg[u]--;
            if (deg[u] == 0) Q.push(u), ans[u] = ans[v] + 1;
        }
    }
    return sz(ts) != (n + m);
}

int main() {
    fill(par, par + MAXN, -1);
    fill(Sz, Sz + MAXN, 1);
    scanf("%lld%lld", &n, &m);
    for (ll i = 1; i <= n; i++) {
        scanf("%s", A[i] + 1);
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') Union(i, n + j);
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') continue;
            if (Find(i) == Find(n + j)) return !printf("No\n");
            if (A[i][j] == '<') adj[Find(i)].push_back(Find(j + n)), deg[j + n]++;
            if (A[i][j] == '>') adj[Find(j + n)].push_back(Find(i)), deg[i]++;
        }
    }
    if (Topo()) return !printf("No\n");
    printf("Yes\n");
    for (ll i = 1; i <= n + m; i++) {
        printf("%lld ", ans[Find(i)]);
        if (i == n) printf("\n");
    }
    return 0;
}


/// IN THE NAME OF METAL
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}

const ll MAXN = 5e3 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7;
ll n, m, ans[MAXN], par[MAXN], Sz[MAXN], mark[MAXN], deg[MAXN];
vector<ll> adj[MAXN];
char A[MAXN][MAXN];

ll Find(ll v) {
    return par[v] == -1 ? v : par[v] = Find(par[v]);
}

ll Union(ll u,ll v) {
    u = Find(u), v = Find(v);
    if (u == v) return 0;
    if (Sz[v] < Sz[u]) swap(u, v);
    par[u] = v;
    Sz[v] += Sz[u];
    return 1;
}

void DFS(ll v, ll id) {
    mark[v] = 1;
    ans[v] = id;
    for (ll u : adj[v]) {
        if (mark[u]) continue;
        DFS(u, id + 1);
    }
}

ll Topo() {
    queue<ll> Q;
    vector<ll> ts;
    for (ll i = 1; i <= n + m; i++) {
        if (deg[i] == 0) Q.push(i), ans[i] = 1;
    }
    while (sz(Q)) {
        ll v = Q.front();
        Q.pop();
        ts.push_back(v);
        for (ll u : adj[v]) {
            deg[u]--;
            if (deg[u] == 0) Q.push(u), ans[u] = ans[v] + 1;
        }
    }
    return sz(ts) != n + m;
}

int main() {
    fill(par, par + MAXN, -1);
    fill(Sz, Sz + MAXN, 1);
    scanf("%lld%lld", &n, &m);
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            cin >> A[i][j];
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') Union(i, n + j);
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') continue;
            if (Find(i) == Find(n + j)) return !printf("No\n");
            if (A[i][j] == '<') adj[Find(i)].push_back(Find(j + n)), deg[j + n]++;
            if (A[i][j] == '>') adj[Find(j + n)].push_back(Find(i)), deg[i]++;
        }
    }
    if (Topo()) return !printf("No\n");
    printf("Yes\n");
    for (ll i = 1; i <= n + m; i++) {
        printf("%lld ", ans[Find(i)]);
        if (i == n) printf("\n");
    }
    return 0;
}


/// IN THE NAME OF METAL
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}

const ll MAXN = 5e3 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7;
ll n, m, ans[MAXN], par[MAXN], Sz[MAXN], mark[MAXN], deg[MAXN];
vector<ll> adj[MAXN];
char A[MAXN][MAXN];

ll Find(ll v) {
    return par[v] == -1 ? v : par[v] = Find(par[v]);
}

ll Union(ll u,ll v) {
    u = Find(u), v = Find(v);
    if (u == v) return 0;
    if (Sz[v] < Sz[u]) swap(u, v);
    par[u] = v;
    Sz[v] += Sz[u];
    return 1;
}

void DFS(ll v, ll id) {
    mark[v] = 1;
    ans[v] = id;
    for (ll u : adj[v]) {
        if (mark[u]) continue;
        DFS(u, id + 1);
    }
}

ll Topo() {
    queue<ll> Q;
    vector<ll> ts;
    for (ll i = 1; i <= n + m; i++) {
        if (deg[i] == 0) Q.push(i), ans[i] = 1;
    }
    while (sz(Q)) {
        ll v = Q.front();
        Q.pop();
        ts.push_back(v);
        for (ll u : adj[v]) {
            deg[u]--;
            if (deg[u] == 0) Q.push(u), ans[u] = ans[v] + 1;
        }
    }
    return sz(ts) != (n + m);
}

int main() {
    fill(par, par + MAXN, -1);
    fill(Sz, Sz + MAXN, 1);
    scanf("%lld%lld", &n, &m);
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            cin >> A[i][j];
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') Union(i, n + j);
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') continue;
            if (Find(i) == Find(n + j)) return !printf("No\n");
            if (A[i][j] == '<') adj[Find(i)].push_back(Find(j + n)), deg[j + n]++;
            if (A[i][j] == '>') adj[Find(j + n)].push_back(Find(i)), deg[i]++;
        }
    }
    if (Topo()) return !printf("No\n");
    printf("Yes\n");
    for (ll i = 1; i <= n + m; i++) {
        printf("%lld ", ans[Find(i)]);
        if (i == n) printf("\n");
    }
    return 0;
}


/// IN THE NAME OF METAL
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}

const ll MAXN = 5e3 + 10;
const ll INF = 8e18;
const ll MOD = 1e9 + 7;
ll n, m, ans[MAXN], par[MAXN], Sz[MAXN], mark[MAXN], deg[MAXN];
vector<ll> adj[MAXN];
char A[MAXN][MAXN];

ll Find(ll v) {
    return par[v] == -1 ? v : par[v] = Find(par[v]);
}

ll Union(ll u,ll v) {
    u = Find(u), v = Find(v);
    if (u == v) return 0;
    if (Sz[v] < Sz[u]) swap(u, v);
    par[u] = v;
    Sz[v] += Sz[u];
    return 1;
}

void DFS(ll v, ll id) {
    mark[v] = 1;
    ans[v] = id;
    for (ll u : adj[v]) {
        if (mark[u]) continue;
        DFS(u, id + 1);
    }
}

ll Topo() {
    queue<ll> Q;
    vector<ll> ts;
    for (ll i = 1; i <= n + m; i++) {
        if (deg[i] == 0) Q.push(i), ans[i] = 1;
    }
    while (sz(Q)) {
        ll v = Q.front();
        Q.pop();
        ts.push_back(v);
        for (ll u : adj[v]) {
            deg[u]--;
            if (deg[u] == 0) Q.push(u), ans[u] = ans[v] + 1;
        }
    }
    return sz(ts) != (n + m);
}

int main() {
    fill(par, par + MAXN, -1);
    fill(Sz, Sz + MAXN, 1);
    scanf("%lld%lld", &n, &m);
    for (ll i = 1; i <= n; i++) {
        scanf("%s", A[i] + 1);
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') Union(i, n + j);
        }
    }
    for (ll i = 1; i <= n; i++) {
        for (ll j = 1; j <= m; j++) {
            if (A[i][j] == '=') continue;
            if (Find(i) == Find(n + j)) return !printf("No\n");
            if (A[i][j] == '<') adj[Find(i)].push_back(Find(j + n)), deg[j + n]++;
            if (A[i][j] == '>') adj[Find(j + n)].push_back(Find(i)), deg[i]++;
        }
    }
    if (Topo()) return !printf("No\n");
    printf("Yes\n");
    for (ll i = 1; i <= n + m; i++) {
        printf("%lld ", ans[Find(i)]);
        if (i == n) printf("\n");
    }
    return 0;
}