#include <bits/stdc++.h>
using namespace std;
class Graph {
 public:
  void AddEdge(const string &id_a, const string &id_b);
  int GetBestColouring() const { return MaxClique((1LL << nodes_.size()) - 1); }

 private:
  vector<set<int>> nodes_;
  unordered_map<string, int> indexes_;
  int GetNodeIndex(const string &id);
  int MaxClique(int64_t mask) const;
};
int Graph::GetNodeIndex(const string &id) {
  auto it = indexes_.find(id);
  if (it != indexes_.end()) {
    return it->second;
  }
  auto index = nodes_.size();
  indexes_.insert({id, index});
  nodes_.push_back(set<int>());
  return index;
}
void Graph::AddEdge(const string &id_a, const string &id_b) {
  auto index_a = GetNodeIndex(id_a);
  auto index_b = GetNodeIndex(id_b);
  nodes_[index_a].insert(index_b);
  nodes_[index_b].insert(index_a);
}
inline int64_t GetBit(int64_t num, int pos) {
  return (num & (1LL << pos)) ? 1 : 0;
}
inline int64_t SetBit(int64_t num, int pos, int value) {
  if (value == 1) {
    num |= (1LL << pos);
  } else {
    num &= (~(1LL << pos));
  }
  return num;
}
int Graph::MaxClique(int64_t mask) const {
  static unordered_map<int64_t, int> memo;
  if (memo.count(mask)) {
    return memo.at(mask);
  }
  auto count = 0;
  for (auto i = 0; i < (int)nodes_.size(); i += 1) {
    if (GetBit(mask, i) == 0) {
      continue;
    }
    auto new_mask = mask;
    for (const auto &son : nodes_[i]) {
      new_mask = SetBit(new_mask, son, 0);
    }
    count = max(count, 1 + MaxClique(new_mask));
    count = max(count, MaxClique(SetBit(mask, i, 0)));
    break;
  }
  return memo[mask] = count;
}
void AddComp(const set<string> &friends, Graph &graph) {
  for (auto i = friends.begin(); i != friends.end(); ++i) {
    for (auto j = i; j != friends.end(); ++j) {
      graph.AddEdge(*i, *j);
    }
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int events, friends;
  cin >> events >> friends;
  Graph graph;
  set<string> curr_comp;
  for (auto i = 0; i < events; i += 1) {
    int type;
    cin >> type;
    if (type == 1) {
      AddComp(curr_comp, graph);
      curr_comp.clear();
      continue;
    }
    string name;
    cin >> name;
    curr_comp.insert(name);
  }
  AddComp(curr_comp, graph);
  auto res = graph.GetBestColouring();
  cout << res << "\n";
  return 0;
}

### Prompt

Your challenge is to write a Cpp solution to the following problem:

Hiasat registered a new account in NeckoForces and when his friends found out about that, each one of them asked to use his name as Hiasat's handle.

Luckily for Hiasat, he can change his handle in some points in time. Also he knows the exact moments friends will visit his profile page. Formally, you are given a sequence of events of two types:

  * 1 — Hiasat can change his handle. 
  * 2 s — friend s visits Hiasat's profile. 



The friend s will be happy, if each time he visits Hiasat's profile his handle would be s.

Hiasat asks you to help him, find the maximum possible number of happy friends he can get.

Input

The first line contains two integers n and m (1 ≤ n ≤ 10^5, 1 ≤ m ≤ 40) — the number of events and the number of friends.

Then n lines follow, each denoting an event of one of two types: 

  * 1 — Hiasat can change his handle. 
  * 2 s — friend s (1 ≤ |s| ≤ 40) visits Hiasat's profile. 



It's guaranteed, that each friend's name consists only of lowercase Latin letters.

It's guaranteed, that the first event is always of the first type and each friend will visit Hiasat's profile at least once.

Output

Print a single integer — the maximum number of happy friends.

Examples

Input


5 3
1
2 motarack
2 mike
1
2 light


Output


2


Input


4 3
1
2 alice
2 bob
2 tanyaromanova


Output


1

Note

In the first example, the best way is to change the handle to the "motarack" in the first event and to the "light" in the fourth event. This way, "motarack" and "light" will be happy, but "mike" will not.

In the second example, you can choose either "alice", "bob" or "tanyaromanova" and only that friend will be happy.

### Response

```cpp
#include <bits/stdc++.h>
using namespace std;
class Graph {
 public:
  void AddEdge(const string &id_a, const string &id_b);
  int GetBestColouring() const { return MaxClique((1LL << nodes_.size()) - 1); }

 private:
  vector<set<int>> nodes_;
  unordered_map<string, int> indexes_;
  int GetNodeIndex(const string &id);
  int MaxClique(int64_t mask) const;
};
int Graph::GetNodeIndex(const string &id) {
  auto it = indexes_.find(id);
  if (it != indexes_.end()) {
    return it->second;
  }
  auto index = nodes_.size();
  indexes_.insert({id, index});
  nodes_.push_back(set<int>());
  return index;
}
void Graph::AddEdge(const string &id_a, const string &id_b) {
  auto index_a = GetNodeIndex(id_a);
  auto index_b = GetNodeIndex(id_b);
  nodes_[index_a].insert(index_b);
  nodes_[index_b].insert(index_a);
}
inline int64_t GetBit(int64_t num, int pos) {
  return (num & (1LL << pos)) ? 1 : 0;
}
inline int64_t SetBit(int64_t num, int pos, int value) {
  if (value == 1) {
    num |= (1LL << pos);
  } else {
    num &= (~(1LL << pos));
  }
  return num;
}
int Graph::MaxClique(int64_t mask) const {
  static unordered_map<int64_t, int> memo;
  if (memo.count(mask)) {
    return memo.at(mask);
  }
  auto count = 0;
  for (auto i = 0; i < (int)nodes_.size(); i += 1) {
    if (GetBit(mask, i) == 0) {
      continue;
    }
    auto new_mask = mask;
    for (const auto &son : nodes_[i]) {
      new_mask = SetBit(new_mask, son, 0);
    }
    count = max(count, 1 + MaxClique(new_mask));
    count = max(count, MaxClique(SetBit(mask, i, 0)));
    break;
  }
  return memo[mask] = count;
}
void AddComp(const set<string> &friends, Graph &graph) {
  for (auto i = friends.begin(); i != friends.end(); ++i) {
    for (auto j = i; j != friends.end(); ++j) {
      graph.AddEdge(*i, *j);
    }
  }
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int events, friends;
  cin >> events >> friends;
  Graph graph;
  set<string> curr_comp;
  for (auto i = 0; i < events; i += 1) {
    int type;
    cin >> type;
    if (type == 1) {
      AddComp(curr_comp, graph);
      curr_comp.clear();
      continue;
    }
    string name;
    cin >> name;
    curr_comp.insert(name);
  }
  AddComp(curr_comp, graph);
  auto res = graph.GetBestColouring();
  cout << res << "\n";
  return 0;
}

```