#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using ull = uint64_t;
using uint = uint32_t;
using VI = vector<int>;
using VL = vector<ll>;
using VVI = vector<vector<int>>;
using VVL = vector<vector<ll>>;
using PII = pair<int, int>;
using PLL = pair<ll, ll>;
const double PI = acos(-1.0);
namespace Backlight {
const int __BUFFER_SIZE__ = 1 << 20;
bool NEOF = 1;
int __top;
char __buf[__BUFFER_SIZE__], *__p1 = __buf, *__p2 = __buf, __stk[996];
template <typename T>
T MIN(T a, T b) {
  return min(a, b);
}
template <typename First, typename... Rest>
First MIN(First f, Rest... r) {
  return min(f, MIN(r...));
}
template <typename T>
T MAX(T a, T b) {
  return max(a, b);
}
template <typename First, typename... Rest>
First MAX(First f, Rest... r) {
  return max(f, MAX(r...));
}
template <typename T>
void updMin(T &a, T b) {
  if (a > b) a = b;
}
template <typename T>
void updMax(T &a, T b) {
  if (a < b) a = b;
}
inline char nc() {
  return __p1 == __p2 && NEOF &&
                 (__p2 =
                      (__p1 = __buf) + fread(__buf, 1, __BUFFER_SIZE__, stdin),
                  __p1 == __p2)
             ? (NEOF = 0, EOF)
             : *__p1++;
}
template <typename T>
inline bool read(T &x) {
  char c = nc();
  bool f = 0;
  x = 0;
  while (!isdigit(c)) c == '-' && (f = 1), c = nc();
  while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = nc();
  if (f) x = -x;
  return NEOF;
}
inline bool need(char c) { return (c != '\n') && (c != ' '); }
inline bool read(char &a) {
  while ((a = nc()) && need(a) && NEOF)
    ;
  return NEOF;
}
inline bool read(char *a) {
  while ((*a = nc()) && need(*a) && NEOF) ++a;
  *a = '\0';
  return NEOF;
}
inline bool read(double &x) {
  bool f = 0;
  char c = nc();
  x = 0;
  while (!isdigit(c)) {
    f |= (c == '-');
    c = nc();
  }
  while (isdigit(c)) {
    x = x * 10.0 + (c ^ 48);
    c = nc();
  }
  if (c == '.') {
    double temp = 1;
    c = nc();
    while (isdigit(c)) {
      temp = temp / 10.0;
      x = x + temp * (c ^ 48);
      c = nc();
    }
  }
  if (f) x = -x;
  return NEOF;
}
template <typename First, typename... Rest>
inline bool read(First &f, Rest &...r) {
  read(f);
  return read(r...);
}
template <typename T>
inline void print(T x) {
  if (x < 0) putchar('-'), x = -x;
  if (x == 0) {
    putchar('0');
    return;
  }
  __top = 0;
  while (x) {
    __stk[++__top] = x % 10 + '0';
    x /= 10;
  }
  while (__top) {
    putchar(__stk[__top]);
    --__top;
  }
}
template <typename First, typename... Rest>
inline void print(First f, Rest... r) {
  print(f);
  putchar(' ');
  print(r...);
}
template <typename T>
inline void println(T x) {
  print(x);
  putchar('\n');
}
template <typename First, typename... Rest>
inline void println(First f, Rest... r) {
  print(f);
  putchar(' ');
  println(r...);
}
template <typename T>
inline void _dbg(const char *format, T value) {
  cerr << format << '=' << value << endl;
}
template <typename First, typename... Rest>
inline void _dbg(const char *format, First f, Rest... r) {
  while (*format != ',') cerr << *format++;
  cerr << '=' << f << ", ";
  _dbg(format + 1, r...);
}
template <typename T>
ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto v : V) os << v << ",";
  return os << " ]";
}
template <typename T>
ostream &operator<<(ostream &os, set<T> V) {
  os << "[ ";
  for (auto v : V) os << v << ",";
  return os << " ]";
}
template <typename T>
ostream &operator<<(ostream &os, multiset<T> V) {
  os << "[ ";
  for (auto v : V) os << v << ",";
  return os << " ]";
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, map<T1, T2> V) {
  os << "[ ";
  for (auto v : V) os << v << ",";
  return os << " ]";
}
template <typename L, typename R>
ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}
}  // namespace Backlight
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int l, int r) { return l + rng() % (r - l + 1); }
const int N = 5e5 + 5;
const int M = 3e6 + 5;
const int K = 1e7 + 5;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const ll LLINF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
void solve(int Case) {
  int n, k;
  cin >> n >> k;
  VI used(26);
  vector<string> ss(n * k);
  for (int i = (0); i < (n); ++i) {
    int p;
    cin >> p;
    for (int j = (0); j < (k); ++j) {
      cin >> ss[p * n + j];
      for (const auto &c : ss[p * n + j]) used[c - 'a'] = 1;
    }
  }
  int alpha = 0;
  for (int v : used)
    if (v) ++alpha;
  VVI G(26);
  VI deg(26);
  auto fail = []() {
    puts("IMPOSSIBLE");
    exit(0);
  };
  auto add = [&](int i, int j) {
    int n = (int((ss[i]).size())), m = (int((ss[j]).size()));
    for (int _ = (0); _ < (min(n, m)); ++_) {
      if (ss[i][_] != ss[j][_]) {
        int u = ss[i][_] - 'a', v = ss[j][_] - 'a';
        G[u].push_back(v);
        ++deg[v];
        return;
      }
    }
    if (n > m) fail();
  };
  int j = -1;
  for (int i = (0); i < (n * k); ++i)
    if ((int((ss[i]).size()))) {
      if (j != -1) add(j, i);
      j = i;
    }
  string t;
  queue<int> q;
  for (int i = (0); i < (26); ++i)
    if (used[i] == 1 && deg[i] == 0) q.push(i);
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    t += char(u + 'a');
    for (int v : G[u]) {
      --deg[v];
      if (deg[v] == 0) q.push(v);
    }
  }
  if ((int((t).size())) != alpha) fail();
  cout << t << endl;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int T = 1;
  for (int _ = 1; _ <= T; _++) solve(_);
  return 0;
}
