#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
using namespace std;
vector<string> vec[1003], v;
bool mat[26][26], flag, ok[26], vis[26], run[26];
int ind[26];
inline bool func(int x, int y) {
  vector<int> vs, vt;
  for (int i = 0; i < v[x].size(); i++) vs.push_back(v[x][i]);
  for (int i = 0; i < v[y].size(); i++) vt.push_back(v[y][i]);
  reverse(vs.begin(), vs.end());
  reverse(vt.begin(), vt.end());
  while (!vs.empty() && !vt.empty()) {
    if (vt.back() != vs.back())
      return mat[vs.back() - 'a'][vt.back() - 'a'] = 1;
    else
      vs.pop_back(), vt.pop_back();
  }
  if (!vs.empty())
    return 0;
  else
    return 1;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  flag = 1;
  string str;
  int n, k, p;
  cin >> n >> k;
  for (int i = 0; i < n; i++) {
    cin >> p;
    for (int j = 0; j < k; j++) {
      cin >> str, vec[p].emplace_back(str);
      for (int l = 0; l < str.size(); l++) ok[str[l] - 'a'] = 1;
    }
  }
  for (int i = 0; i < n; i++)
    for (int j = 0; j < k; j++) v.emplace_back(vec[i][j]);
  for (int i = 0; i < v.size() - 1 && flag; i++) flag = func(i, i + 1);
  for (int i = 0; i < 26; i++)
    for (int j = 0; j < 26; j++) ind[j] += mat[i][j];
  int cnt = 0, tot = 0;
  for (int i = 0; i < 26; i++) tot += ok[i];
  queue<int> q;
  for (int i = 0; i < 26; i++)
    if (ok[i] && !ind[i]) q.push(i);
  vector<int> res;
  while (!q.empty() && flag) {
    int x = q.front();
    q.pop();
    res.push_back(x);
    for (int i = 0; i < 26; i++)
      if (mat[x][i]) {
        ind[i]--;
        if (!ind[i]) q.push(i);
      }
  }
  if (flag && res.size() == tot) {
    for (int i = 0; i < res.size(); i++) cout << (char)(res[i] + 'a');
    cout << "\n";
  } else
    cout << "IMPOSSIBLE\n";
  return 0;
}
