#include <bits/stdc++.h>
using namespace std;
const long long N = 2e5 + 5, inf = 1e18;
long long p[N];
std::vector<string> g[N];
vector<long long> gg[N];
bool present[30];
void add_edge(const string& a, const string& b) {
  if (a == b) return;
  long long i = 0, j = 0;
  while (i < (long long)(a.size()) && j < (long long)(b.size())) {
    if (a[i] != b[j]) {
      long long from = a[i] - 'a' + 1;
      long long to = b[j] - 'a' + 1;
      gg[from].push_back(to);
      return;
    }
    i++, j++;
  }
  assert((long long)(a.size()) != (long long)(b.size()));
  if ((long long)(a.size()) > (long long)(b.size())) {
    cout << "IMPOSSIBLE\n";
    exit(0);
  } else {
  }
}
vector<long long> order;
bool toposort(long long n) {
  queue<long long> q;
  vector<long long> indeg(n + 1, 0);
  for (long long i = 1; i <= n; i++)
    for (auto& it : gg[i]) indeg[it]++;
  for (long long i = 1; i <= n; i++) {
    if (!indeg[i]) q.push(i);
  }
  while (!q.empty()) {
    long long u = q.front();
    q.pop();
    order.push_back(u);
    for (auto& v : gg[u]) {
      indeg[v]--;
      if (!indeg[v]) q.push(v);
    }
  }
  return (long long)(order.size()) == n;
}
int32_t main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long n, k;
  cin >> n >> k;
  for (long long i = 1; i <= n; i++) {
    cin >> p[i];
    ++p[i];
    for (long long j = 1; j <= k; j++) {
      string s;
      cin >> s;
      for (char ch : s) present[ch - 'a' + 1] = true;
      g[p[i]].push_back(s);
    }
  }
  vector<string> all;
  for (long long i = 1; i <= N; i++) {
    for (string nxt : g[i]) {
      all.push_back(nxt);
    }
  }
  for (long long i = 1; i < (long long)(all.size()); i++) {
    add_edge(all[i - 1], all[i]);
  }
  if (toposort(30)) {
    for (long long x : order)
      if (present[x]) {
        char ch = (char)(x - 1 + 'a');
        cout << ch;
      }
    cout << '\n';
  } else {
    cout << "IMPOSSIBLE\n";
  }
}
