#include <bits/stdc++.h>
long long modinverse(long long a, long long b, long long s0 = 1,
                     long long s1 = 0) {
  if (!b)
    return s0;
  else
    return modinverse(b, a % b, s1, s0 - s1 * (a / b));
}
long long gcd(long long a, long long b) {
  if (!b)
    return a;
  else
    return gcd(b, a % b);
}
long long mul(long long a, long long b, long long m) {
  long long q = (long double)a * (long double)b / (long double)m;
  long long r = a * b - q * m;
  return (r + 5 * m) % m;
}
long long safemod(long long a, long long m) { return (a % m + m) % m; }
struct equation {
  equation(long long a, long long m) { mod = m, ans = a, valid = true; }
  equation() { valid = false; }
  equation(equation a, equation b) {
    if (!a.valid || !b.valid) {
      valid = false;
      return;
    }
    long long g = gcd(a.mod, b.mod);
    if ((a.ans - b.ans) % g != 0) {
      valid = false;
      return;
    }
    valid = true;
    mod = a.mod * (b.mod / g);
    ans = a.ans + mul(mul(a.mod, modinverse(a.mod, b.mod), mod),
                      (b.ans - a.ans) / g, mod);
    ans = safemod(ans, mod);
  }
  long long mod, ans;
  bool valid;
  void print() {
    if (!valid)
      std::cout << "equation is not valid\n";
    else
      std::cout << "equation is " << ans << " mod " << mod << '\n';
  }
};
struct i_t {
  i_t() { valid = false; }
  i_t(equation cur) {
    eq = cur;
    valid = true;
  }
  i_t(i_t a, i_t b) {
    if (!a.valid)
      *this = b;
    else if (!b.valid)
      *this = a;
    else {
      eq = equation(a.eq, b.eq);
      l = a.l;
      r = b.r;
      valid = true;
    }
  }
  equation eq;
  bool valid;
  int l, r;
  void print() { eq.print(); }
};
class Seg_Tree {
 public:
  Seg_Tree(std::vector<equation> _a) {
    a = _a;
    n = a.size();
    st.resize(4 * n);
    build(0, n - 1, 0);
  }
  i_t qry(int l, int r) { return qry(0, n - 1, l, r, 0); }

 private:
  int left(int x) { return x + x + 1; }
  int right(int x) { return x + x + 2; }
  int n;
  std::vector<i_t> st;
  std::vector<equation> a;
  void build(int l, int r, int pos) {
    if (l == r) {
      st[pos] = i_t(a[l]);
      st[pos].l = st[pos].r = l;
      return;
    }
    int mid = (l + r) / 2;
    build(l, mid, left(pos));
    build(mid + 1, r, right(pos));
    st[pos] = i_t(st[left(pos)], st[right(pos)]);
  }
  i_t qry(int l, int r, int i, int j, int pos) {
    if (l >= i && r <= j)
      return st[pos];
    else if (r < i || l > j)
      return i_t();
    int mid = (l + r) / 2;
    return i_t(qry(l, mid, i, j, left(pos)), qry(mid + 1, r, i, j, right(pos)));
  }
};
const int ms = 200200;
int n, m;
int k[ms];
std::vector<std::pair<int, equation> > where[ms];
int segment(int l, int r, int num) {
  std::vector<equation> eq;
  for (int i = l; i < r; i++) eq.push_back(where[num][i].second);
  Seg_Tree tree(eq);
  int ans = 0;
  int lp = 0;
  for (int i = 0; i < eq.size(); i++) {
    while (!tree.qry(lp, i).eq.valid) lp++;
    ans = std::max(ans, i - lp + 1);
  }
  return ans;
}
int solve(int num) {
  if (where[num].size() == 0) return 0;
  int ans = 0;
  int l = 0;
  int r = 1;
  while (l < where[num].size()) {
    r = l + 1;
    while (r < where[num].size() &&
           where[num][r - 1].first + 1 == where[num][r].first)
      r++;
    ans = std::max(ans, segment(l, r, num));
    l = r;
  }
  return ans;
}
int main() {
  std::cin >> n >> m;
  for (int i = 0; i < n; i++) {
    std::cin >> k[i];
    for (int j = 0; j < k[i]; j++) {
      int temp;
      std::cin >> temp;
      where[temp].push_back(std::pair<int, equation>(i, equation(j, k[i])));
    }
  }
  std::vector<int> ans;
  for (int i = 1; i <= m; i++) ans.push_back(solve(i));
  for (int i = 0; i < ans.size(); i++) std::cout << ans[i] << '\n';
}
