#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <algorithm>	// require sort next_permutation count __gcd reverse etc.
#include <cstdlib>	// require abs exit atof atoi 
#include <cstdio>		// require scanf printf
#include <functional>
#include <numeric>	// require accumulate
#include <cmath>		// require fabs
#include <climits>
#include <limits>
#include <cfloat>
#include <iomanip>	// require setw
#include <sstream>	// require stringstream 
#include <cstring>	// require memset
#include <cctype>		// require tolower, toupper
#include <fstream>	// require freopen
#include <ctime>		// require srand
#define rep(i,n) for(int i=0;i<(n);i++)
#define ALL(A) A.begin(), A.end()
#define INF 1<<28

using namespace std;

typedef long long ll;
typedef pair<int, int> P;

P time2num (string s ){
	int n = s.length();
	rep (i, n ) if (s[i] == ':' || s[i] == '-' ) s[i] = ' ';

	stringstream ss(s);
	int ah, am, bh, bm;
	ss >> ah >> am >> bh >> bm;

	int res1 = ah*60 + am;
	int res2 = bh*60 + bm;

	return P(res1, res2 ); // 開始時間、終了時間
}

bool is_cover(P a, P b ){ // a ⊃ b
	return (a.first <= b.first && a.second >= b.second );
}

bool is_match (P a, P b ){
	return (a.first == b.first && a.second == b.second );
} 

vector<P> parse_string (string s ){
	stringstream ss (s );
	int k; string t;
	ss >> k;

	vector<P> res; res.clear();
	while (k-- ){
		ss >> t;
		res.push_back (time2num(t ) );
	} // end while

	return res;
}

const int MAX_V = 205;

// 辺を表す構造体（行き先、容量、逆辺）
struct edge{ int to, cap, rev; };

vector<edge> G[MAX_V];	// グラフの隣接リスト表現
bool used[MAX_V];			// DFS ですでに調べたかのフラグ

bool init_graph(void ){
	memset (used, false, sizeof (used ) );
	rep (i, MAX_V) G[i].clear();
}

// from から to へ向かう容量 cap の辺をグラフに追加する
void add_edge (int from, int to, int cap ){
	G[from].push_back ((edge){to, cap, G[to].size() } );
	G[to].push_back ((edge){from, 0, G[from].size()-1 } );
}

// 増加バスを DFS で探す
int dfs (int v, int t, int f ){
	if (v == t ) return f;
	used[v] = true;
	for (int i = 0; i < G[v].size(); i++ ){
		edge &e = G[v][i];
		if (!used[e.to] && e.cap > 0 ){
			int d = dfs (e.to, t, min (f, e.cap ) );
			if (d > 0 ){
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			} // end if
		} // end if
	} // end for

	return 0;
}

// s から t への最大流を求める
int max_flow (int s, int t ){
	int flow = 0;
	for (;; ){
		memset (used, false, sizeof (used ) );
		int f = dfs (s, t, INF );
		if (f == 0 ) return flow;
		flow += f;
	} // end for
}

int s2i (string s ){
	stringstream ss (s );
	int res;
	ss >> res;

	return res;
}

vector<P> teacher_t[105];				
vector<P> student_t[105];				

int main()
{
	ios_base::sync_with_stdio(0);
	string str = "";
	getline (cin, str );
	vector<P> class_t = parse_string (str );	// 授業に使える時間帯

	getline (cin, str );
	
	int n = s2i (str );
	// 先生 i の時間帯が授業に使える時間帯にOKな時間帯 を求める
	rep (i, n ) teacher_t[i].clear();			
	rep (i, n ){
		getline (cin, str );
		vector<P> t2 = parse_string (str );	// 先生 i の時間帯情報
		rep (j2, class_t.size() ){
			bool ok = false;
			rep (i2, t2.size() ){
				ok = is_cover(t2[i2], class_t[j2]  );
				if (ok ) teacher_t[i].push_back (class_t[j2] );
			} // end rep
		} // end rep
	} // end rep

	getline (cin, str );
	int m = s2i (str );
	// 生徒 j の時間帯が授業に使える時間帯にOKな時間帯 を求める
	rep (j, m ) student_t[j].clear();			
	rep (j, m ){
		getline (cin, str );
		vector<P> s2 = parse_string (str );	// 生徒 i の時間帯情報
		rep (j2, class_t.size() ){
			bool ok = false;
			rep (i2, s2.size() ){
				ok = is_cover(s2[i2], class_t[j2] );
				if (ok ) student_t[j].push_back (class_t[j2] );
			} // end rep
		} // end rep
	} // end rep


	// 0 〜 n-1 ; 先生に対応する頂点
	// n 〜 n+m-1;	生徒に対応する頂点
	int S = n+m;
	int T = S+1;

	int res = 0;
	rep (cnt, class_t.size() ){

		// グラフの初期化
		init_graph();
		// S と先生 を結ぶ
		rep (i, n ){
			add_edge (S, i, 1 );
		} // end rep
		// 生徒と T を結ぶ
		rep (j, m ){
			add_edge (n+j, T, 1 );
		} // end rep

		// 先生 i と 生徒 j へエッジを張る
		rep (i, n ){
			rep (i2, teacher_t[i].size() ){
				P cur1 = teacher_t[i][i2];
				if (!is_match (class_t[cnt], cur1 ) ) continue;
				rep (j, m ){
					rep (j2, student_t[j].size() ){
						P cur2 = student_t[j][j2];
						if (!is_match (class_t[cnt], cur2 ) ) continue;
						add_edge (i, n+j, 1 );
					} // end rep
				} // end rep
			} // end rep
		} // end rep

		int curr = max_flow(S, T );
		res += curr;
	} // end rep

	cout << res << endl;
	return 0;
}

Measured memory_bytes: 1556