#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3")
struct unionfind {
  int length;
  vector<int> parent;
  unionfind(int s) {
    length = s;
    parent.assign(s, 0);
    std::iota(parent.begin(), parent.end(), 0);
  }
  int rep(int x) {
    while (x != parent[x]) {
      parent[x] = parent[parent[x]];
      x = parent[x];
    }
    return x;
  }
  void unite(int a, int b) {
    a = rep(a);
    b = rep(b);
    if (a == b) return;
    parent[b] = a;
  }
  inline bool query(int a, int b) { return rep(a) == rep(b); }
};
vector<int> p1, p2;
vector<int> pos1, pos2;
int main() {
  int n, k;
  cin >> n >> k;
  p1.assign(n, 0);
  p2.assign(n, 0);
  pos1.assign(n, 0);
  pos2.assign(n, 0);
  for (int i = 0; i < n; ++i) {
    cin >> p1[i];
    p1[i]--;
    pos1[p1[i]] = i;
  }
  for (int i = 0; i < n; ++i) {
    cin >> p2[i];
    p2[i]--;
    pos2[p2[i]] = i;
  }
  unionfind uf(n);
  vector<int> reps(n, -1);
  int cg = 0;
  set<int> s1;
  set<int> s2;
  s1.insert(p1[0]);
  s2.insert(p2[0]);
  int e1, e2;
  for (int i = 0; i < n; ++i) {
    e1 = p1[i];
    e2 = p2[i];
    s1.insert(e1);
    s2.insert(e2);
    if (s1.count(e1) and s2.count(e1)) {
      s1.erase(e1);
      s2.erase(e1);
    }
    if (s1.count(e2) and s2.count(e2)) {
      s1.erase(e2);
      s2.erase(e2);
    }
    if (s1.size() == 0 and s2.size() == 0) {
      reps[i] = cg++;
    }
  }
  int cur = -1;
  for (int i = n - 1; i >= 0; --i) {
    if (reps[i] != -1) cur = reps[i];
    reps[i] = cur;
  }
  set<int> unique;
  for (int i = 0; i < n; ++i) {
    unique.insert(reps[i]);
  };
  if (unique.size() < k) {
    cout << "NO" << endl;
    return 0;
  }
  map<int, int> sng;
  cur = 0;
  for (auto i : unique) {
    sng[i] = 'a' + cur;
    if (cur < k - 1) cur++;
  }
  cout << "YES" << endl;
  vector<int> tmp;
  tmp.assign(n, 'a');
  for (int i = 0; i < n; ++i) tmp[p1[i]] = sng[reps[i]];
  for (auto i : tmp) cout << (char)i;
  cout << endl;
  return 0;
}
