#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL

int ans, q, m, type, cnt; string t;
map<string, int> names;
vector<pii> v;
int adj[50][50];
vector<int> e[50];
long long mask;

void dfs(int v, int cur = 0) {
	if (v == m + 1) {
		ans = max(ans, cur);
		return;
	}

	int ok = 1;
	for (int u : e[v]) {
		if (mask & (1LL << u)) ok = 0;
	}

	if (ok) {
		mask ^= (1LL << v);
		dfs(v + 1, cur + 1);
		mask ^= (1LL << v);
	}
	dfs(v + 1, cur);
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	cin >> q >> m;
	names.clear();
	for (int i = 0; i < q; i++) {
		cin >> type;
		if (type == 1) v.pb({1, -1});
		else {
			cin >> t;
			if (!names.count(t)) names[t] = ++cnt;
			v.pb({2, names[t]});
		}
	}
	v.pb({1, -1}); q++;

	long long bs = 0;
	for (int i = 0; i < q; i++) {
		cerr << v[i].fi << ' ' << v[i].se << '\n';
		if (v[i].fi == 1) {
			for (int x = 1; x <= m; x++) {
				if (bs & (1LL << x)) {
					for (int y = x + 1; y <= m; y++) {
						if (bs & (1LL << y)) adj[x][y] = adj[y][x] = 1;
					}
				}
			}
			bs = 0;
		}
		else bs |= (1LL << v[i].se);
	}

	for (int i = 1; i <= m; i++)
	for (int j = 1; j <= m; j++) if (adj[i][j]) e[i].pb(j);

	dfs(1);

	cout << ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL

int ans, q, m, type, cnt; string t;
map<string, int> names;
vector<pii> v;
int adj[50][50];
vector<int> e[50];
long long mask;

void dfs(int v) {
	if (v == m + 1) {
		ans = max(ans, __builtin_popcount(mask));
		return;
	}

	int ok = 1;
	for (int u : e[v]) {
		if (mask & (1LL << u)) ok = 0;
	}

	if (ok) {
		mask ^= (1LL << v);
		dfs(v + 1);
		mask ^= (1LL << v);
	}
	dfs(v + 1);
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	cin >> q >> m;
	names.clear();
	for (int i = 0; i < q; i++) {
		cin >> type;
		if (type == 1) v.pb({1, -1});
		else {
			cin >> t;
			if (!names.count(t)) names[t] = ++cnt;
			v.pb({2, names[t]});
		}
	}
	v.pb({1, -1}); q++;

	long long bs = 0;
	for (int i = 0; i < q; i++) {
		cerr << v[i].fi << ' ' << v[i].se << '\n';
		if (v[i].fi == 1) {
			for (int x = 1; x <= m; x++) {
				if (bs & (1LL << x)) {
					for (int y = x + 1; y <= m; y++) {
						if (bs & (1LL << y)) adj[x][y] = adj[y][x] = 1;
					}
				}
			}
			bs = 0;
		}
		else bs |= (1LL << v[i].se);
	}

	for (int i = 1; i <= m; i++)
	for (int j = 1; j <= m; j++) if (adj[i][j]) e[i].pb(j);

	dfs(1);

	cout << ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 1
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL

bool adj[50][50]; // 0-based
unordered_map<long long, int> dp1, dp2; // meet in the middle
int n;

void buildGraph() {
	int events; cin >> events;
	map<string, int> m;
	vector<int> cur;

	for (int i = 0, type; i < events; i++) {
		cin >> type;
		if (type == 1) {
			for (int x : cur) for (int y : cur) {
				if (x != y) adj[x][y] = 1;
			}
			cur.clear();
		}
		else {
			string name; cin >> name;
			if (!m.count(name)) m[name] = m.size();
			cur.pb(m[name]);
		}
	}

	n = m.size();
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	buildGraph();

	int mi = n / 2;

	dp1[0] = dp2[0] = 0;

	for (long long bs = 1; bs < (1LL << mi); bs += 1LL) { // for first n/2 nodes, compute max for each bitset
		vector<int> cur;
		for (int node = 0; node < mi; node++) {
			if ((1LL << node) & bs) {
				cur.pb(node);
				dp1[bs] = max(dp1[bs], dp1[bs ^ (1LL << node)]);
			}
		}
		bool invalid = 0;
		for (int x : cur) for (int y : cur) if (adj[x][y]) invalid = 1;
		if (not invalid) dp1[bs] = cur.size();
	}

	for (long long bs = 1LL << mi; bs < (1LL << (n - mi)); bs += 1LL << mi) { // for second n/2 nodes, compute max for each bitset
		vector<int> cur;
		for (int node = mi; node < n; node++) {
			if ((1LL << node) & bs) {
				cur.pb(node);
				dp2[bs] = max(dp2[bs], dp2[bs ^ (1LL << node)]);
			}
		}
		bool invalid = 0;
		for (int x : cur) for (int y : cur) if (adj[x][y]) invalid = 1;
		if (not invalid) dp2[bs] = cur.size();
	}

	int ans = 0;

	for (long long bs = 1; bs < (1LL << mi); bs += 1LL) { // meet in the middle
		long long getHalf = ((1LL << (n - mi)) - 1) << mi;
		for (int node = 0; node < mi; node++) {
			if ((1LL << node) & bs) {
				for (int i = mi; i < n; i++) if (adj[node][i]) getHalf &= (~(1LL << i));
			}
		}
		ans = max(ans, dp1[bs] + dp2[getHalf]);
	}

	cout << ans;
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define DEBUG 0
#define cerr if (DEBUG) cerr
#define fprintf if (DEBUG) fprintf
#define local freopen("in.txt","r",stdin);
#define test cerr<<"hi\n";
#define tr(x) cerr<<#x" "<<x<<'\n';
#define fi first
#define se second
#define HH1 402653189
#define HH2 1610612741
#define INF 0x3f3f3f3f
#define tii tuple<int,int,int>
#define npos string::npos

using namespace std;

#define MOD 1000000007LL

bool adj[50][50]; // 0-based
unordered_map<long long, int> dp1, dp2; // meet in the middle
int n;

void buildGraph() {
	int events; cin >> events >> n;
	map<string, int> m;
	set<int> cur;

	for (int i = 0, type; i < events; i++) {
		cin >> type;
		if (type == 1) {
			for (int x : cur) for (int y : cur) {
				if (x != y) adj[x][y] = 1;
			}
			cur.clear();
		}
		else {
			string name; cin >> name;
			if (!m.count(name)) {
				int k = m.size();
				m[name] = k;
			}
			cur.insert(m[name]);
		}
	}
	for (int x : cur) for (int y : cur) {
		if (x != y) adj[x][y] = adj[y][x] = 1;
	}
	for (auto op : m) {
		cerr << op.fi << ' ' << op.se << '\n';
	}
}

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	buildGraph();

	int mi = n / 2;

	dp1[0] = dp2[0] = 0;

	for (long long bs = 1; bs < (1LL << mi); bs += 1LL) { // for first n/2 nodes, compute max for each bitset
		vector<int> cur;
		for (int node = 0; node < mi; node++) {
			if ((1LL << node) & bs) {
				cur.pb(node);
				dp1[bs] = max(dp1[bs], dp1[bs ^ (1LL << node)]);
			}
		}
		bool invalid = 0;
		for (int x : cur) for (int y : cur) if (adj[x][y]) invalid = 1;
		if (not invalid) dp1[bs] = cur.size();

		tr(bs)
		tr(dp1[bs])
	}

	if (n == 40) exit(0);

	for (long long bs = (1LL << mi); bs < (1LL << n); bs += (1LL << mi)) { // for second n/2 nodes, compute max for each bitset
		vector<int> cur;
		for (int node = mi; node < n; node++) {
			if ((1LL << node) & bs) {
				cur.pb(node);
				dp2[bs] = max(dp2[bs], dp2[bs ^ (1LL << node)]);
			}
		}
		bool invalid = 0;
		for (int x : cur) for (int y : cur) if (adj[x][y]) invalid = 1;
		if (not invalid) dp2[bs] = cur.size();
	}

	int ans = 0;

	for (long long bs = 0; bs < (1LL << mi); bs += 1LL) { // meet in the middle
		long long getHalf = ((1LL << (n - mi)) - 1) << mi;
		for (int node = 0; node < mi; node++) {
			if ((1LL << node) & bs) {
				for (int i = mi; i < n; i++) {
					if (adj[node][i]) {
						getHalf &= (~(1LL << i));
					}
				}
			}
		}
		ans = max(ans, dp1[bs] + dp2[getHalf]);
	}

	cout << ans;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) cerr << adj[i][j];
		cerr << '\n';
	}

}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long disable_bit(long long a,int bit){
	return a & (~(1LL << bit));
}

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if (memo.find(mask)!=memo.end())
		return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(disable_bit(mask, a),ad_mask,memo);//choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//choose a
	long long res2=res1;
	if((mask ^ (1LL << a))>0 && __builtin_popcountll(mask ^ (1LL << a)) > __builtin_popcountll(res1))
		res2=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++) ad_mask[i]^=((1LL << m)-1);

	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcountll(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

int disable_bit(long long a,int bit){
	return a & (~(1LL << bit));
}

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if (memo.find(mask)!=memo.end())
		return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(disable_bit(mask, a),ad_mask,memo);//choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n);
	for(int i=0;i<n;i++){
		long long mask=0;
		for(int ch:ad[i]) mask |= (1LL << ch);
		ad_mask[i]=mask;
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=(res_mask & (1LL << i));
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			ad_mask[v] |= mask;
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= (1LL << v);
			}
			mask |= (1LL << v);
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if (memo.find(mask)!=memo.end())
		return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++) ad_mask[i]^=((1LL << m)-1);

	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcount(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

int disable_bit(long long a,int bit){
	return a & (~(1LL << bit));
}

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if (memo.find(mask)!=memo.end())
		return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(disable_bit(mask, a),ad_mask,memo);//choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n);
	for(int i=0;i<n;i++){
		long long mask=0;
		for(int ch:ad[i]) mask |= (1LL << ch);
		ad_mask[i]=mask;
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=(res_mask & (1LL << i));
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//choose a
	long long res2=res1;
	if((__builtin_popcountll(mask & ad_mask[a])+1) > res1)
		res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++) ad_mask[i]^=((1LL << m)-1);

	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcountll(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}/*
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}*/
	for(int i=0;i<m;i++) ad_mask[i]^=(1LL << m)-1;
	/*vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";*/
	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcount(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long disable_bit(long long a,int bit){
	return a & (~(1LL << bit));
}

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if (memo.find(mask)!=memo.end())
		return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(disable_bit(mask, a),ad_mask,memo);//choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

int disable_bit(long long a,int bit){
	return a & (~(1LL << bit));
}

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if (memo.find(mask)!=memo.end())
		return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(disable_bit(mask, a),ad_mask,memo);//choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcount(res1) > __builtin_popcount(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
vector<bool> max_clique(vector<vector<int>>& ad){
	int n=ad.size();
	vector<long long> ad_mask(n,0);
	for(int i=0;i<n;i++){
		for(int ch:ad[i]) ad_mask[i] |= (1LL << ch);
	}
	unordered_map<long long,long long> memo;
	long long res_mask=max_clique((1LL << n)-1,ad_mask,memo);
	vector<bool> res(n);
	for(int i=0;i<n;i++) res[i]=((res_mask >> i) & 1);
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<m;j++){
			if((ad_mask[i] >> j) & 1) continue;
			if(i==j) continue;
			ad[i].push_back(j);
		}
	}
	vector<bool> res=max_clique(ad);
	int ires=0;
	for(int i=0;i<m;i++) if(res[i]) ires++;
	cout << ires << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	long long res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++) ad_mask[i]^=((1LL << m)-1);

	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcountll(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//do not choose a
	if(res1==0) return mask;
	long long res2=res1;
	if((mask & ad_mask[a])>0 && (__builtin_popcountll(mask & ad_mask[a])+1) > __builtin_popcountll(res1))
		res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++) ad_mask[i]^=((1LL << m)-1);

	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcountll(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

long long max_clique(long long mask,vector<long long>& ad_mask,unordered_map<long long, long long>& memo){// O(1.44^n)
	if(memo.find(mask)!=memo.end()) return memo[mask];
	if(mask==0) return 0;
	int a=__builtin_ctzll(mask);
	long long res1=max_clique(mask ^ (1LL << a),ad_mask,memo);//choose a
	long long res2=0;
	if(__builtin_popcountll(mask & ad_mask[a]) > res1)
		res2=(max_clique(mask & ad_mask[a],ad_mask,memo) | (1LL << a));//do not choose a
	long long res=(__builtin_popcountll(res1) > __builtin_popcountll(res2))?res1:res2;
	memo[mask]=res;
	return res;
}
int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int name=0;
	unordered_map<string,int> mp;
	vector<vector<int>> ad(m);
	long long mask=0;
	vector<long long> ad_mask(m,0);
	for(int i=0;i<n;i++){
		int q;
		cin >> q;
		if(q==1){
			mask=0;
		}else{
			string str;
			cin >> str;
			if(mp.find(str)==mp.end()) mp[str]=name++;
			int v=mp[str];
			if((mask & (1LL << v))) continue;
			mask |= (1LL << v);
			for(int j=0;j<m;j++){
				if((mask & (1LL << j)))
					ad_mask[j] |= mask;
			}
		}
	}
	for(int i=0;i<m;i++) ad_mask[i]^=((1LL << m)-1);

	unordered_map<long long,long long> mp2;
	long long res=max_clique((1LL << m)-1,ad_mask,mp2);
	cout << __builtin_popcountll(res) << "\n";
	return 0;
}


#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
#include<string>
#include<functional>
#include<unordered_map>

using namespace std;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	int n,m;
	cin >> n >> m;
	int q;
	cin  >> q;
	int count=1;
	int res=0;
	while(count < n){
		unordered_map<string,int> mp;
		cin >> q;
		int smax=0;
		while(q==2){
			string key;
			cin >> key;
			count++;
			if(mp.find(key)==mp.end()) mp[key]=1;
			else mp[key]=mp[key]+1;

			smax=max(smax,mp[key]);
			if(count==n) break;
			cin >> q;
		}
		res+=smax;
		count++;
	}
	cout << res << "\n";
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define int long long

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1LL << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1LL << j;
			}
		}
	}

	for (int i = 0; i < m; ++i) {
		g[i] |= 1LL << i;
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1LL << b_size) - 1, kill_b = ((1LL << a_size) - 1) << b_size;
	vector<int> max_aclique(1LL << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1LL << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1LL << a_size; ++a_mask) {
		mask = a_mask << b_size;
		bool check = false;
		ull partOfB = (1LL << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			if (!(mask & (1LL << b_size + i))) continue;
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & ~(1LL << b_size + i) & mask) {
				check = true;
				break;
			}
		}
		if (check) continue;
		int kek = 0;
		int temp_mask = mask;
		while (temp_mask) {
			temp_mask &= (temp_mask - 1);
			++kek;
		}
		ans = max(ans, kek + max_aclique[partOfB]);
	}
	cout << ans << endl;
	return 0;
}

signed main() {
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1LL << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1LL << j;
			}
		}
	}

	for (int i = 0; i < m; ++i) {
		g[i] |= 1LL << i;
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1LL << b_size) - 1, kill_b = ((1LL << a_size) - 1) << b_size;
	vector<int> max_aclique(1LL << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1LL << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1LL << a_size; ++a_mask) {
		mask = a_mask << b_size;
		bool check = false;
		ull partOfB = (1LL << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			if (!(mask & (1LL << b_size + i))) continue;
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & ~(1LL << b_size + i) & mask) {
				check = true;
				break;
			}
		}
		if (check) continue;
		ans = max(ans, __builtin_popcount(mask) + max_aclique[partOfB]);
	}
	cout << ans << endl;
	return 0;
}

int main() {
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define int long long

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1LL << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1LL << j;
			}
		}
	}

	for (int i = 0; i < m; ++i) {
		g[i] |= 1LL << i;
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1LL << b_size) - 1, kill_b = ((1LL << a_size) - 1) << b_size;
	vector<int> max_aclique(1LL << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1LL << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1LL << a_size; ++a_mask) {
		mask = a_mask << b_size;
		bool check = false;
		ull partOfB = (1LL << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			if (!(mask & (1LL << b_size + i))) continue;
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & ~(1LL << b_size + i) & mask) {
				check = true;
				break;
			}
		}
		if (check) continue;
		ans = max(ans, __builtin_popcountl(mask) + max_aclique[partOfB]);
	}
	cout << ans << endl;
	return 0;
}

signed main() {
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1 << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1 << j;
			}
		}
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1 << b_size) - 1, kill_b = ((1 << a_size) - 1) << b_size;
	vector<int> max_aclique(1 << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1 << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1 << a_size; ++a_mask) {
		mask = a_mask << b_size;
		bool check = false;
		ull partOfB = (1 << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			if (!(mask & (1 << b_size + i))) continue;
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & ~(1 << b_size + i) & mask) {
				check = true;
				break;
			}
		}
		if (check) {
			continue;
		}
		ans = max(ans, __builtin_popcount(mask) + max_aclique[partOfB]);
	}
	cout << ans << endl;
	return 0;
}

int main() {
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1 << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1 << j;
			}
		}
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1 << b_size) - 1, kill_b = ((1 << a_size) - 1) << b_size;
	vector<int> max_aclique(1 << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1 << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1 << a_size; ++a_mask) {
		mask = a_mask << b_size;
		bool check = false;
		ull partOfB = (1 << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			if (!(mask & (1 << a_size + i))) continue;
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & ~(1 << b_size + i) & mask) {
				check = true;
				break;
			}
		}
		if (check) {
			continue;
		}
		ans = max(ans, __builtin_popcount(a_mask) + max_aclique[partOfB]);
	}
	cout << ans << endl;
	return 0;
}

int main() {
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <unordered_map>

#define FAST_KEK ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

#define int long long

using namespace std;

vector<int> q;
unordered_map<string, int> kek;
signed solve() {
	int n, m;
	cin >> n >> m;
	int i, x;
	for (i = 0; i < n; ++i) {
		cin >> x;
		if (x == 1) {
			++i;
			break;
		}
	}
	bool last_edinichka = 1;
	string s;
	vector<int> w(m);
	for ( ; i < n; ++i) {
		cin >> x;
		if (x == 2) {
			last_edinichka = 0;
			cin >> s;
			int temp = sz(kek);
			if (kek.find(s) == kek.end()) {
				kek[s] = temp;
			}
			int ind = kek[s];
			w[ind]++;
		}
		else if (last_edinichka) {
			continue;
		}
		else {
			last_edinichka = 1;
			int mxw = 0;
			for (auto &i : w) {
				mxw = max(mxw, i);
			}
			q.pb(mxw);
			fill(all(w), 0);
		}
	}
	if (!last_edinichka) {
		int mxw = 0;
		for (auto &i : w) {
			mxw = max(mxw, i);
		}
		q.pb(mxw);
	}

	int ans = 0;
	for (int i = 0; i < sz(q); ++i) {
		ans += q[i];
	}
	cout << ans << endl;
}

signed main() {
	FAST_KEK

	solve();

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
#include <unordered_map>

#define FAST_KEK ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

#define int long long

using namespace std;

vector<int> q;
unordered_map<string, int> kek;
signed solve() {
	int n, m;
	cin >> n >> m;
	int i, x;
	string s;
	for (i = 0; i < n; ++i) {
		cin >> x;
		if (x == 1) {
			++i;
			break;
		}
		else {
			cin >> s;
		}
	}
	bool last_edinichka = 1;
	vector<int> w(m);
	for ( ; i < n; ++i) {
		cin >> x;
		if (x == 2) {
			last_edinichka = 0;
			cin >> s;
			int temp = sz(kek);
			if (kek.find(s) == kek.end()) {
				kek[s] = temp;
			}
			int ind = kek[s];
			w[ind]++;
		}
		else if (last_edinichka) {
			continue;
		}
		else {
			last_edinichka = 1;
			int mxw = 0;
			for (auto &i : w) {
				mxw = max(mxw, i);
			}
			q.pb(mxw);
			fill(all(w), 0);
		}
	}
	if (!last_edinichka) {
		int mxw = 0;
		for (auto &i : w) {
			mxw = max(mxw, i);
		}
		q.pb(mxw);
	}

	int ans = 0;
	for (int i = 0; i < sz(q); ++i) {
		ans += q[i];
	}
	cout << ans << endl;
}

signed main() {
	FAST_KEK

	solve();

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define int long long

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1LL << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1LL << j;
			}
		}
	}

	for (int i = 0; i < m; ++i) {
		g[i] |= 1LL << i;
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1LL << b_size) - 1, kill_b = ((1LL << a_size) - 1) << b_size;
	vector<int> max_aclique(1LL << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1LL << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1LL << a_size; ++a_mask) {
		mask = a_mask << b_size;
		bool check = false;
		ull partOfB = (1LL << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			if (!(mask & (1LL << b_size + i))) continue;
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & ~(1LL << b_size + i) & mask) {
				check = true;
				break;
			}
		}
		if (check) continue;
		ans = max(ans, __builtin_popcountll(mask) + max_aclique[partOfB]);
	}
	cout << ans << endl;
	return 0;
}

signed main() {
	solve();
	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

#include <bitset>

#define sz(a) (int) a.size()
#define all(a) a.begin(), a.end()
#define pb push_back

using namespace std;

typedef unsigned long long ull;

void read(int &m, vector<ull> &g) {
	int n;
	cin >> n >> m;
	g.resize(m);
	string s;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			--n;
			break;
		}
		else {
			cin >> s;
		}
	}
	vector<int> cur;
	unordered_map<string, int> mp;
	int last = 1;
	for (int x; n > 0; --n) {
		cin >> x;
		if (x == 1) {
			if (last == 1) {
				continue;
			}
			else {
				for (auto &i : cur) {
					for (auto &j : cur) {
						g[i] |= 1 << j;
					}
				}
				cur.clear();
				last = 1;
			}
		}
		else {
			cin >> s;
			int temp = sz(mp);
			if (mp.find(s) == mp.end()) {
				mp[s] = temp;
			}
			cur.pb(mp[s]);
			last = 2;
		}
	}
	if (last == 2) {
		for (auto &i : cur) {
			for (auto &j : cur) {
				g[i] |= 1 << j;
			}
		}
	}
}

int solve() {
	int m;
	vector<ull> g;
	read(m, g);
	int a_size = (m + 1) / 2, b_size = m / 2;
	swap(a_size, b_size);
	ull kill_a = (1 << b_size) - 1, kill_b = ((1 << a_size) - 1) << b_size;
	vector<int> max_aclique(1 << b_size);
	int b = 0;
	for (ull b_mask = 1; b_mask < 1 << b_size; ++b_mask) {
		if (b_mask == 2LL << b) {
			++b;
		}
		max_aclique[b_mask] = max(max_aclique[b_mask ^ (1LL << b)],
								 1 + max_aclique[b_mask & ~g[b] & kill_a]);
	}

	int ans = 0;
	for (ull a_mask = 0, mask; a_mask < 1 << a_size; ++a_mask) {
		bool check = false;
		ull partOfB = (1 << b_size) - 1;
		for (int i = 0; i < a_size; ++i) {
			partOfB &= ~g[b_size + i];
			if (g[b_size + i] & kill_b & ~(1 << b_size + i) & a_mask) {
				check = true;
				break;
			}
		}
		if (check) continue;
		ans = max(ans, __builtin_popcount(a_mask) + max_aclique[partOfB]);
	}
	cout << ans << endl;
}

int main() {
	solve();
	return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|(1<<idx))+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20){
mask|=(1<<(buff[i]-20));
}
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
//cout<<mask<<endl;
}
for(int i=0;i<1100000;i++)
lolz.push_back({i,REC(0,(((1<<20)-1)^i))});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[counter];
counter++;
TEMP/=2;
}
//cout<<mask<<endl;
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
//if(REC2(0,mask)+lolz[i].second==2)
//cout<<mask<<' '<<lolz[i].second<<' '<<lolz[i].first<<endl;
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|(1<<idx))+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
exit(-1);
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
//cout<<mask<<endl;
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
lolz.push_back({i,REC(0,i)});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1048576],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<20;i++){
for(int l=0;l<1048576;l++){
DP[i+1][l]=max(DP[i][l],DP[i+1][l]);
if(F[i]&&(!(l&F[i]))){
DP[i+1][l|(1<<i)]=max(DP[i][l]+1,DP[i+1][l|(1<<i)]);
}
}
}
for(int i=0;i<1048576;i++){
lolz.push_back({i,DP[20][i]});
//if(DP[20][i])
//cout<<DP[20][i]<<endl;
}
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20){
mask|=(1<<(buff[i]-20));
}
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
//cout<<mask<<endl;
}
for(int i=0;i<21;i++)
for(int l=0;l<1048576;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[counter];
counter++;
TEMP/=2;
}
//cout<<mask<<endl;
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
//if(REC2(0,mask)+lolz[i].second==2)
//cout<<mask<<' '<<lolz[i].second<<' '<<lolz[i].first<<endl;
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|F[idx])+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
exit(-1);
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|S[idx])+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
//cout<<REC(0,0)<<endl;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
if(REC(0,i))
lolz.push_back({i,REC(0,i)});
lolz.push_back({0,0});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1048576],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
DP[0][0]=1;
for(int i=0;i<20;i++){
for(int l=0;l<1048576;l++){
DP[i+1][l]=max(DP[i][l],DP[i+1][l]);
if(F[i]&&(!(l&F[i]))&&DP[i][l]){
DP[i+1][l|(1<<i)]=1;
}
}
}
for(int i=0;i<1048576;i++){
if(DP[20][i]){
int TEMP=i,counter=0;
while(TEMP)
counter+=TEMP%2,TEMP/=2;
lolz.push_back({i,counter});
}
}
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20){
mask|=(1<<(buff[i]-20));
}
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
//cout<<mask<<endl;
}
for(int i=0;i<21;i++)
for(int l=0;l<1048576;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[counter];
counter++;
TEMP/=2;
}
//cout<<mask<<endl;
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
//if(REC2(0,mask)+lolz[i].second==2)
//cout<<mask<<' '<<lolz[i].second<<' '<<lolz[i].first<<endl;
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|(1<<idx))+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
//cout<<mask<<endl;
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
lolz.push_back({i,REC(0,i)});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[counter];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|F[idx])+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|S[idx])+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<20;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
//cout<<REC(0,0)<<endl;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
if(DP[20][i])
lolz.push_back({i,DP[20][i]});
lolz.push_back({0,0});
for(int i=0;i<20;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|F[idx])+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
exit(-1);
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|S[idx])+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
if(REC(0,i))
lolz.push_back({i,REC(0,i)});
lolz.push_back({0,0});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
if(REC2(0,mask))
exit(-1);
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|(1<<idx))+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
//cout<<mask<<endl;
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
lolz.push_back({i,REC(0,i)});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
//#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1048576],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|(1<<idx))+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<20;i++){
for(int l=0;l<1048576;l++){
DP[i+1][l]=max(DP[i][l],DP[i+1][l]);
if(F[i]&&(!(l&F[i]))){
DP[i+1][l|(1<<i)]=max(DP[i][l]+1,DP[i+1][l|(1<<i)]);
}
}
}
for(int i=0;i<1048576;i++){
lolz.push_back({i,DP[20][i]});
//if(DP[20][i])
//cout<<DP[20][i]<<endl;
}
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20){
mask|=(1<<(buff[i]-20));
}
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
//cout<<mask<<endl;
}
for(int i=0;i<21;i++)
for(int l=0;l<1048576;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[counter];
counter++;
TEMP/=2;
}
//cout<<mask<<endl;
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
//if(REC2(0,mask)+lolz[i].second==2)
//cout<<mask<<' '<<lolz[i].second<<' '<<lolz[i].first<<endl;
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|F[idx])+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
exit(-1);
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|S[idx])+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
if(REC(0,i))
lolz.push_back({i,REC(0,i)});
lolz.push_back({0,0});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


#include <bits/stdc++.h>
#define endl '\n'
#define modulo 1000000007
#define int long long
#define PI acos(-1)
//#pragma GCC optimize("-Ofast")
//#pragma GCC optimize("trapv")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
#define sinDegrees(x) sin((x) * PI / 180.0)
#define cosDegrees(x) cos((x) * PI / 180.0)
#define tanDegrees(x) tan((x) * PI / 180.0)
#define atanDegrees(x) atan(x)* 180.0 / PI
#define asinDegrees(x) asin(x)* 180.0 / PI
#define EPS 0.000000001
using namespace std;
int power(int x,int y,int m)
{
int temp;
if(y == 0)
return 1;
temp = (power(x, y/2,m))%m;
if (y%2 == 0)
return ((temp%m)*temp);
else
return ((x*temp%m)*temp%m)%m;
}
int inv(int x,int m=modulo)
{
return (power(x,m-2,m))%m;
}
///IOI 2021 isA
int n,m,DP[21][1100000],Q,C,mask;
int F[20],S[20],T[20];
string s;
map<string,int>lol;
vector<int>HIST;
vector<pair<int,int>>lolz;
int REC(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(F[idx]&&(!(F[idx]&masker)))
return DP[idx][masker]=max(REC(idx+1,masker),REC(idx+1,masker|F[idx])+1);
return DP[idx][masker]=REC(idx+1,masker);
}
int REC2(int idx,int masker){
if(idx>=20)
return 0;
if(DP[idx][masker]+1)
return DP[idx][masker];
if(S[idx]&&(!(S[idx]&masker))){
exit(-1);
return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|S[idx])+1);
}
return DP[idx][masker]=REC2(idx+1,masker);
}
int32_t main()
{
//freopen("output.txt","w",stdout);
//freopen("colors.in","r",stdin);
cin.tie(0),iostream::sync_with_stdio(0);
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>Q;
if(Q==1)
HIST.push_back(-1);
else{
cin>>s;
if(lol.find(s)!=lol.end())
HIST.push_back(lol.at(s));
else
lol.insert({s,C}),HIST.push_back(C),C++;
}
}
vector<int>buff;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]<20)
mask|=(1<<buff[i]);
}
flag=0;
buff.clear();
//cout<<mask<<endl;
F[l]=mask;
}
for(int l=20;l<40;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
S[l-20]=mask;
}
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
for(int l=0;l<20;l++){
bool flag=0;
mask=0;
for(int i=0;i<n;i++){
if(HIST[i]+1){
buff.push_back(HIST[i]);
if(HIST[i]==l)
flag=1;
}
else{
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
}
}
if(flag)
for(int i=0;i<buff.size();i++){
if(buff[i]>=20)
mask|=(1<<(buff[i]-20));
}
flag=0;
buff.clear();
T[l]=mask;
}
for(int i=0;i<1100000;i++)
lolz.push_back({i,REC(0,i)});
for(int i=0;i<21;i++)
for(int l=0;l<1100000;l++)
DP[i][l]=-1;
int maxer=0;
for(int i=0;i<lolz.size();i++){
int TEMP=lolz[i].first,counter=0;
mask=0;
while(TEMP){
if(TEMP%2)
mask|=T[(1<<counter)];
counter++;
TEMP/=2;
}
//cout<<REC2(0,0)<<endl;
maxer=max(maxer,REC2(0,mask)+lolz[i].second);
}
cout<<maxer;
return 0;
}


    #include <bits/stdc++.h>
    #define endl '\n'
    #define modulo 1000000007
    #define int long long
    #define PI acos(-1)
    //#pragma GCC optimize("-Ofast")
    //#pragma GCC optimize("trapv")
    #pragma GCC target("sse,sse2,sse3,ssse3,sse4,sse4.2,popcnt,abm,mmx,avx2,tune=native")
    #pragma GCC optimize("-ffast-math")
    #pragma GCC optimize("-funroll-loops")
    #pragma GCC optimize("-funroll-all-loops,-fpeel-loops,-funswitch-loops")
    #define sinDegrees(x) sin((x) * PI / 180.0)
    #define cosDegrees(x) cos((x) * PI / 180.0)
    #define tanDegrees(x) tan((x) * PI / 180.0)
    #define atanDegrees(x) atan(x)* 180.0 / PI
    #define asinDegrees(x) asin(x)* 180.0 / PI
    #define EPS 0.000000001
    using namespace std;
    int power(int x,int y,int m)
    {
    int temp;
    if(y == 0)
    return 1;
    temp = (power(x, y/2,m))%m;
    if (y%2 == 0)
    return ((temp%m)*temp);
    else
    return ((x*temp%m)*temp%m)%m;
    }
    int inv(int x,int m=modulo)
    {
    return (power(x,m-2,m))%m;
    }
    ///IOI 2021 isA
    int n,m,DP[21][1048576],Q,C,mask;
    int F[20],S[20],T[20];
    string s;
    map<string,int>lol;
    vector<int>HIST;
    vector<pair<int,int>>lolz;
    int REC2(int idx,int masker){
    if(idx>=20)
    return 0;
    if(DP[idx][masker]+1)
    return DP[idx][masker];
    if(S[idx]&&(!((1<<idx)&masker))){
    return DP[idx][masker]=max(REC2(idx+1,masker),REC2(idx+1,masker|S[idx])+1);
    }
    return DP[idx][masker]=REC2(idx+1,masker);
    }
    int32_t main()
    {
    //freopen("output.txt","w",stdout);
    //freopen("colors.in","r",stdin);
    cin.tie(0),iostream::sync_with_stdio(0);
    cin>>n>>m;
    for(int i=0;i<n;i++){
    cin>>Q;
    if(Q==1)
    HIST.push_back(-1);
    else{
    cin>>s;
    if(lol.find(s)!=lol.end())
    HIST.push_back(lol.at(s));
    else
    lol.insert({s,C}),HIST.push_back(C),C++;
    }
    }
    vector<int>buff;
    for(int l=0;l<20;l++){
    bool flag=0;
    mask=0;
    for(int i=0;i<n;i++){
    if(HIST[i]+1){
    buff.push_back(HIST[i]);
    if(HIST[i]==l)
    flag=1;
    }
    else{
    if(flag)
    for(int i=0;i<buff.size();i++){
    if(buff[i]<20)
    mask|=(1<<buff[i]);
    }
    flag=0;
    buff.clear();
    }
    }
    if(flag)
    for(int i=0;i<buff.size();i++){
    if(buff[i]<20)
    mask|=(1<<buff[i]);
    }
    flag=0;
    buff.clear();
    F[l]=mask;
    }
    for(int l=20;l<40;l++){
    bool flag=0;
    mask=0;
    for(int i=0;i<n;i++){
    if(HIST[i]+1){
    buff.push_back(HIST[i]);
    if(HIST[i]==l)
    flag=1;
    }
    else{
    if(flag)
    for(int i=0;i<buff.size();i++){
    if(buff[i]>=20)
    mask|=(1<<(buff[i]-20));
    }
    flag=0;
    buff.clear();
    }
    }
    if(flag)
    for(int i=0;i<buff.size();i++){
    if(buff[i]>=20)
    mask|=(1<<(buff[i]-20));
    }
    flag=0;
    buff.clear();
    S[l-20]=mask;
    }
    DP[0][0]=1;
    for(int i=0;i<20;i++){
    for(int l=0;l<1048576;l++){
    DP[i+1][l]=max(DP[i][l],DP[i+1][l]);
    if(F[i]&&(!(l&F[i]))&&DP[i][l]){
    DP[i+1][l|(1<<i)]=1;
    }
    }
    }
    for(int i=0;i<1048576;i++){
    if(DP[20][i]){
    int TEMP=i,counter=0;
    while(TEMP)
    counter+=TEMP%2,TEMP/=2;
    lolz.push_back({i,counter});
    }
    }
    for(int l=0;l<20;l++){
    bool flag=0;
    mask=0;
    for(int i=0;i<n;i++){
    if(HIST[i]+1){
    buff.push_back(HIST[i]);
    if(HIST[i]==l)
    flag=1;
    }
    else{
    if(flag)
    for(int i=0;i<buff.size();i++){
    if(buff[i]>=20){
    mask|=(1<<(buff[i]-20));
    }
    }
    flag=0;
    buff.clear();
    }
    }
    if(flag)
    for(int i=0;i<buff.size();i++){
    if(buff[i]>=20)
    mask|=(1<<(buff[i]-20));
    }
    flag=0;
    buff.clear();
    T[l]=mask;
    //cout<<mask<<endl;
    }
    for(int i=0;i<21;i++)
    for(int l=0;l<1048576;l++)
    DP[i][l]=-1;
    int maxer=0;
    for(int i=0;i<lolz.size();i++){
    int TEMP=lolz[i].first,counter=0;
    mask=0;
    while(TEMP){
    if(TEMP%2)
    mask|=T[counter];
    counter++;
    TEMP/=2;
    }
    //cout<<mask<<endl;
    //cout<<REC2(0,0)<<endl;
    maxer=max(maxer,REC2(0,mask)+lolz[i].second);
    //if(REC2(0,mask)+lolz[i].second==2)
    //cout<<mask<<' '<<lolz[i].second<<' '<<lolz[i].first<<endl;
    }
    cout<<maxer;
    return 0;
    }


#include <bits/stdc++.h>
using namespace std;
#define finish(x) return cout << x << endl, 0
#define ll long long

int n, m, dp[1 << 20], valid[1 << 20][2];
ll bad[41];
map <string, int> mp;
vector <int> a;

int idx(string s){
    if(mp.find(s) == mp.end()){
        int sz = mp.size();
        mp[s] = sz;
    }
    return mp[s];
}
void go(int mask){
    for(int i = 0 ; i < m ; i++)
        for(int j = 0 ; j < m ; j++)
            if(i != j && (mask & (1LL << i)) && (mask & (1LL << j)))
                bad[i] |= (1 << j);
}
int good(int x, int y){
    return !(bad[x] & (1LL << y));
}
int main(){
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    ll mask = 0;
    for(int i = 0 ; i < n ; i++){
        int x;
        cin >> x;
        if(x == 1){
            go(mask);
            mask = 0;
        }
        else{
            string s;
            cin >> s;
            mask |= (1LL << idx(s));
        }
    }
    go(mask);
    int l = m / 2;
    int r = m - l;
    valid[0][0] = 1;
    for(int i = 1 ; i < (1 << l) ; i++){
        int cur = -1;
        for(int j = 0 ; j < l ; j++){
            if(((1 << j) & i) == 0) continue;
            if(valid[i ^ (1 << j)][0]) cur = j;
        }
        if(cur == -1) continue;
        int ok = 1;
        for(int j = 0 ; j < l ; j++){
            if(((1 << j) & i) == 0) continue;
            if(j == cur) continue;
            if(!good(cur, j)) ok = 0;
        }
        if(ok) valid[i][0] = 1;
    }
    valid[0][1] = 1;
    for(int i = 1 ; i < (1 << r) ; i++){
        int cur = -1;
        for(int j = 0 ; j < r ; j++){
            if(((1 << j) & i) == 0) continue;
            if(valid[i ^ (1 << j)][1]) cur = j;
        }
        if(cur == -1) continue;
        int ok = 1;
        for(int j = 0 ; j < r ; j++){
            if(((1 << j) & i) == 0) continue;
            if(j == cur) continue;
            if(!good(cur + l, j + l)) ok = 0;
        }
        if(ok) valid[i][1] = 1;
    }
    int ans = 0;
    for(int i = 1 ; i < (1 << l) ; i++){
        if(valid[i][0]) dp[i] = __builtin_popcount(i);
        else{
            for(int j = 0 ; j < l ; j++){
                if((i & (1 << j)) == 0) continue;
                dp[i] = max(dp[i], dp[i ^ (1 << j)]);
            }
        }
        ans = max(ans, dp[i]);
    }
    for(int i = 0 ; i < (1 << r) ; i++){
        if(!valid[i][1]) continue;
        int mask = 0;
        for(int j = 0 ; j < l ; j++){
            if(bad[j] & (i << l)) continue;
            mask |= (1 << j);
        }
        ans = max(ans, __builtin_popcount(i) + dp[mask]);
    }
    cout << ans << endl;
}