#include <bits/stdc++.h>
using namespace std;
class Solution {
 public:
  int maximize(vector<pair<int, string>>& events, int m) {
    map<string, int> indices;
    int n = events.size();
    int pre = -1;
    vector<bool> isValid(m, true);
    vector<vector<bool>> conflicts(m + 1, vector<bool>(m + 1, false));
    set<int> nexts;
    for (int i = 0; i < n; ++i) {
      int t = events[i].first;
      if (t == 1) {
        for (auto it = nexts.begin(); it != nexts.end(); ++it) {
          int u = *it;
          for (auto it2 = it; it2 != nexts.end(); ++it2) {
            int v = *it2;
            if (u == v) {
              continue;
            }
            conflicts[u][v] = true;
            conflicts[v][u] = true;
          }
        }
        nexts.clear();
        pre = i;
      } else {
        string& name = events[i].second;
        int idx = -1;
        if (indices.count(name) == 0) {
          idx = indices.size();
          indices[name] = idx;
        } else {
          idx = indices[name];
        }
        if (pre == -1) {
          isValid[idx] = false;
        } else {
          nexts.insert(idx);
        }
      }
    }
    for (auto it = nexts.begin(); it != nexts.end(); ++it) {
      int u = *it;
      for (auto it2 = it; it2 != nexts.end(); ++it2) {
        int v = *it2;
        if (u == v) {
          continue;
        }
        conflicts[u][v] = true;
        conflicts[v][u] = true;
      }
    }
    nexts.clear();
    vector<int> newIndices(m, -1);
    for (int i = 0, idx = 0; i < m; ++i) {
      if (isValid[i]) {
        newIndices[i] = idx++;
      }
    }
    vector<long long> forbidens(m, 0);
    for (int i = 0; i < m; ++i) {
      int ni = newIndices[i];
      if (ni == -1) {
        continue;
      }
      long long flag = 0;
      for (int j = 0; j < m; ++j) {
        int nj = newIndices[j];
        if (nj == -1 || !conflicts[i][j]) {
          continue;
        }
        flag |= 1LL << nj;
      }
      forbidens[ni] = flag;
    }
    int mm = 0;
    for (int i = 0; i < m; ++i) {
      if (newIndices[i] != -1) {
        ++mm;
      }
    }
    int sz1 = mm / 2;
    int sz2 = mm - sz1;
    int N = 1 << sz1;
    vector<int> cnts(N, 0);
    int res = 0;
    for (int i = 0; i < N; ++i) {
      int valid = true;
      int cnt = 0;
      for (int j = 0; j < sz1; ++j) {
        if (i & (1 << j)) {
          if (i & (forbidens[j])) {
            valid = false;
            break;
          }
          ++cnt;
        }
      }
      if (valid) {
        cnts[i] = cnt;
        res = max(res, cnt);
      }
    }
    for (int j = 0; j < sz1; ++j) {
      for (int i = 0; i < N; ++i) {
        if ((i & (1 << j)) == 0) {
          auto& cnt = cnts[i | (1 << j)];
          cnt = max(cnt, cnts[i]);
        }
      }
    }
    int N2 = 1 << sz2;
    for (int i = 0; i < N2; ++i) {
      bool valid = true;
      long long allows = (1LL << mm) - 1;
      int cnt = 0;
      for (int j = 0; j < sz2; ++j) {
        if (i & (1 << j)) {
          if (i & (forbidens[sz1 + j] >> sz1)) {
            valid = false;
            break;
          }
          allows &= ~forbidens[sz1 + j];
          ++cnt;
        }
      }
      if (valid) {
        allows &= N - 1;
        res = max(res, cnt + cnts[allows]);
      }
    }
    return res;
  }
};
int main(int argc, char** argv) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  Solution sol;
  int n, m;
  cin >> n;
  cin >> m;
  vector<pair<int, string>> events;
  events.reserve(n);
  for (int i = 0; i < n; ++i) {
    int t;
    cin >> t;
    if (t == 1) {
      events.emplace_back(1, "");
    } else {
      string s;
      cin >> s;
      events.emplace_back(2, s);
    }
  }
  cout << sol.maximize(events, m) << "\n";
  return 0;
}
