#include <bits/stdc++.h>
using namespace std;
template <typename... As>
struct tpl : public std::tuple<As...> {
  using std::tuple<As...>::tuple;
  template <typename T = tuple<As...>>
  typename tuple_element<0, T>::type const& x() const {
    return get<0>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<0, T>::type& x() {
    return get<0>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<1, T>::type const& y() const {
    return get<1>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<1, T>::type& y() {
    return get<1>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<2, T>::type const& z() const {
    return get<2>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<2, T>::type& z() {
    return get<2>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<3, T>::type const& w() const {
    return get<3>(*this);
  }
  template <typename T = tuple<As...>>
  typename tuple_element<3, T>::type& w() {
    return get<3>(*this);
  }
};
using llu = long long unsigned;
using pii = tpl<int, int>;
using piii = tpl<int, int, int>;
using piiii = tpl<int, int, int, int>;
using vi = vector<int>;
using vii = vector<pii>;
using viii = vector<piii>;
using vvi = vector<vi>;
using vvii = vector<vii>;
using vviii = vector<viii>;
template <class T>
using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T>
using max_queue = priority_queue<T>;
template <size_t... I>
struct my_index_sequence {
  using type = my_index_sequence;
  static constexpr array<size_t, sizeof...(I)> value = {{I...}};
};
namespace my_index_sequence_detail {
template <typename I, typename J>
struct concat;
template <size_t... I, size_t... J>
struct concat<my_index_sequence<I...>, my_index_sequence<J...>>
    : my_index_sequence<I..., (sizeof...(I) + J)...> {};
template <size_t N>
struct make_index_sequence
    : concat<typename make_index_sequence<N / 2>::type,
             typename make_index_sequence<N - N / 2>::type>::type {};
template <>
struct make_index_sequence<0> : my_index_sequence<> {};
template <>
struct make_index_sequence<1> : my_index_sequence<0> {};
}  // namespace my_index_sequence_detail
template <class... A>
using my_index_sequence_for =
    typename my_index_sequence_detail::make_index_sequence<sizeof...(A)>::type;
template <class T, size_t... I>
void print_tuple(ostream& s, T const& a, my_index_sequence<I...>) {
  using swallow = int[];
  (void)swallow{0, (void(s << (I == 0 ? "" : ", ") << get<I>(a)), 0)...};
}
template <class T>
ostream& print_collection(ostream& s, T const& a);
template <class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a);
template <class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a);
template <class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a);
template <class T, size_t I>
ostream& operator<<(ostream& s, array<T, I> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& operator<<(ostream& s, vector<T> const& a) {
  return print_collection(s, a);
}
template <class T, class U>
ostream& operator<<(ostream& s, multimap<T, U> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& operator<<(ostream& s, multiset<T> const& a) {
  return print_collection(s, a);
}
template <class T, class U>
ostream& operator<<(ostream& s, map<T, U> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& operator<<(ostream& s, set<T> const& a) {
  return print_collection(s, a);
}
template <class T>
ostream& print_collection(ostream& s, T const& a) {
  s << '[';
  for (auto it = begin(a); it != end(a); ++it) {
    s << *it;
    if (it != prev(end(a))) s << " ";
  }
  return s << ']';
}
template <class... A>
ostream& operator<<(ostream& s, tpl<A...> const& a) {
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}
template <class... A>
ostream& operator<<(ostream& s, tuple<A...> const& a) {
  s << '(';
  print_tuple(s, a, my_index_sequence_for<A...>{});
  return s << ')';
}
template <class A, class B>
ostream& operator<<(ostream& s, pair<A, B> const& a) {
  return s << "(" << get<0>(a) << ", " << get<1>(a) << ")";
}
namespace std {
namespace {
template <class T>
inline void hash_combine(size_t& seed, T const& v) {
  seed ^= hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
template <class Tuple, size_t Index = tuple_size<Tuple>::value - 1>
struct HashValueImpl {
  static void apply(size_t& seed, Tuple const& tuple) {
    HashValueImpl<Tuple, Index - 1>::apply(seed, tuple);
    hash_combine(seed, get<Index>(tuple));
  }
};
template <class Tuple>
struct HashValueImpl<Tuple, 0> {
  static void apply(size_t& seed, Tuple const& tuple) {
    hash_combine(seed, get<0>(tuple));
  }
};
}  // namespace
template <typename... TT>
struct hash<tuple<TT...>> {
  size_t operator()(tuple<TT...> const& tt) const {
    size_t seed = 0;
    HashValueImpl<tuple<TT...>>::apply(seed, tt);
    return seed;
  }
};
template <typename... TT>
struct hash<tpl<TT...>> {
  size_t operator()(tpl<TT...> const& tt) const {
    size_t seed = 0;
    HashValueImpl<tuple<TT...>>::apply(seed, tt);
    return seed;
  }
};
}  // namespace std
int read_positive() {
  char c;
  int x = 0;
  do {
    c = getchar();
  } while (c < '0' || c > '9');
  while (c >= '0' && c <= '9') {
    x = 10 * x + (c - '0');
    c = getchar();
  }
  return x;
}
struct MaxFlow {
  struct Edge {
    short from, to, index;
    int cap, flow;
    Edge(int from, int to, int cap, int flow, int index)
        : from(from), to(to), cap(cap), flow(flow), index(index) {}
  };
  int N;
  vector<vector<Edge>> G;
  vector<int> excess;
  vector<int> dist, active, count;
  queue<int> Q;
  MaxFlow(int N = 0)
      : N(N), G(N), excess(N), dist(N), active(N), count(2 * N) {}
  int addNode() {
    N += 1;
    G.emplace_back();
    excess.emplace_back();
    dist.emplace_back();
    active.emplace_back();
    count.emplace_back();
    count.emplace_back();
    return N - 1;
  }
  Edge* addEdge(int from, int to, int cap) {
    G[from].push_back(Edge(from, to, cap, 0, G[to].size()));
    Edge* e = &G[from].back();
    if (from == to) G[from].back().index++;
    G[to].push_back(Edge(to, from, 0, 0, G[from].size() - 1));
    return e;
  }
  void enqueue(int v) {
    if (!active[v] && excess[v] > 0) {
      active[v] = true;
      Q.push(v);
    }
  }
  void push(Edge& e) {
    int amt = min(excess[e.from], e.cap - e.flow);
    if (dist[e.from] <= dist[e.to] || amt == 0) return;
    e.flow += amt;
    G[e.to][e.index].flow -= amt;
    excess[e.to] += amt;
    excess[e.from] -= amt;
    enqueue(e.to);
  }
  void gap(int k) {
    for (int v = 0; v < (int)(N); ++v) {
      if (dist[v] < k) continue;
      count[dist[v]]--;
      dist[v] = max(dist[v], N + 1);
      count[dist[v]]++;
      enqueue(v);
    }
  }
  void relabel(int v) {
    count[dist[v]]--;
    dist[v] = 2 * N;
    for (Edge& e : G[v])
      if (e.cap - e.flow > 0) {
        dist[v] = min(dist[v], dist[e.to] + 1);
      }
    count[dist[v]]++;
    enqueue(v);
  }
  void discharge(int v) {
    for (int i = 0; excess[v] > 0 && i < (int)G[v].size(); ++i) push(G[v][i]);
    if (excess[v] > 0) {
      if (count[dist[v]] == 1) {
        gap(dist[v]);
      } else {
        relabel(v);
      }
    }
  }
  int flow(int s, int t) {
    count[0] = N - 1;
    count[N] = 1;
    dist[s] = N;
    active[s] = active[t] = true;
    for (Edge& e : G[s]) {
      excess[s] += e.cap;
      push(e);
    }
    while (!Q.empty()) {
      int v = Q.front();
      Q.pop();
      active[v] = false;
      discharge(v);
    }
    int totflow = 0;
    for (Edge& e : G[s]) totflow += e.flow;
    return totflow;
  }
};
int A[3000];
char R[3000][3000];
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  int tot = n * (n - 1);
  for (int i = 0; i < (int)(m); ++i) {
    cin >> A[i];
    tot -= A[i];
  }
  for (int i = (m); i <= (int)(n - 1); ++i) {
    A[i] = A[i - 1];
  }
  if (tot < 0) {
    cout << "no" << endl;
    return 0;
  }
  MaxFlow G(2 + 2 * n + 1);
  int S = 0;
  int T = 1;
  int T2 = 2 + 2 * n;
  G.addEdge(T2, T, tot);
  for (int i = 0; i < (int)(n); ++i) {
    G.addEdge(S, 2 + i, 2 * (n - 1 - i));
    for (int j = (i); j <= (int)(n - 1); ++j) {
      G.addEdge(2 + i, 2 + n + j, (i == j) ? (2 * (n - 1)) : 2);
    }
    G.addEdge(2 + n + i, (i < m) ? T : T2, A[i]);
  }
  int f = G.flow(S, T);
  if (f != n * (n - 1)) {
    cout << "no" << endl;
    return 0;
  }
  for (int i = 0; i < (int)(n); ++i) R[i][i] = 'X';
  for (int i = 0; i < (int)(n); ++i)
    for (auto const& e : G.G[2 + i]) {
      int j = e.to - 2 - n;
      if (i == j) continue;
      if (!(j >= 0 && j < n)) continue;
      if (e.flow == 2) {
        R[i][j] = 'L';
        R[j][i] = 'W';
      } else if (e.flow == 1) {
        R[i][j] = R[j][i] = 'D';
      } else {
        R[i][j] = 'W';
        R[j][i] = 'L';
      }
    }
  cout << "yes" << endl;
  for (int i = 0; i < (int)(n); ++i) {
    for (int j = 0; j < (int)(n); ++j) {
      cout << R[i][j];
    }
    cout << '\n';
  }
  cout << flush;
  return 0;
}
