Problem:
Rotate and Rewrite
Two sequences of integers
A:
A
1
A
2
...
A
n
and
B:
B
1
B
2
...
B
m
and
a set of
rewriting rules
of the form
"
x
1
x
2
...
x
k
→
y
"
are given.
The following transformations on each of the sequences are allowed
an arbitrary number of times in an arbitrary order independently.
Rotate
:
  Moving the first element of a sequence to the last.
  That is, transforming a sequence
c
1
c
2
...
c
p
to
c
2
...
c
p
c
1
.
Rewrite
:
  With a rewriting rule
  "
x
1
x
2
...
x
k
→
y
",
  transforming a sequence
c
1
c
2
...
c
i
x
1
x
2
...
x
k
d
1
d
2
...
d
j
to
c
1
c
2
...
c
i
y
d
1
d
2
...
d
j
.
Your task is to determine whether it is possible to transform the two sequences A and B into the same sequence.
If possible, compute the length of the longest of the sequences after such a transformation.
Input
The input consists of multiple datasets. Each dataset has the following form.
n m r
A
1
A
2
...
A
n
B
1
B
2
...
B
m
R
1
...
R
r
The first line of a dataset consists of three positive integers
n
,
m
, and
r,
where
n
(
n
≤ 25) is the length of the sequence A,
m
(
m
≤ 25) is the length of the sequence B, and
r
(
r
≤ 60) is the number of rewriting rules.
The second line contains
n
integers representing the
n
elements of A.
The third line contains
m
integers representing the
m
elements of B.
Each of the last
r
lines describes a rewriting rule in the following form.
k
x
1
x
2
...
x
k
y
The first
k
is an integer (2 ≤
k
≤ 10), which is the length of the left-hand side of the rule.
It is followed by
k
integers
x
1
x
2
...
x
k
,
representing the left-hand side of the rule.
Finally comes an integer
y
, representing the right-hand side.
All of
A
1
, ..,
A
n
,
B
1
, ...,
B
m
,
x
1
, ...,
x
k
, and
y
are in the range between 1 and 30, inclusive.
A line "0 0 0" denotes the end of the input.
Output
For each dataset, if it is possible to transform A and B
to the same sequence, print the length of the longest of
the sequences after such a transformation.
Print
-1
if it is impossible.
Sample Input
3 3 3
1 2 3
4 5 6
2 1 2 5
2 6 4 3
2 5 3 1
3 3 2
1 1 1
2 2 1
2 1 1 2
2 2 2 1
7 1 2
1 1 2 1 4 1 2
4
3 1 4 1 4
3 2 4 2 4
16 14 5
2 1 2 2 1 3 2 1 3 2 2 1 1 3 1 2
2 1 3 1 1 2 3 1 2 2 2 2 1 3
2 3 1 3
3 2 2 2 1
3 2 2 1 2
3 1 2 2 2
4 2 1 2 2 2
0 0 0
Output for the Sample Input
2
-1
1
9

Submitted solutions:

code_snippet: // AOJ #1191 Rotate and Rewrite
// 2025.3.30

#include <bits/stdc++.h>
using namespace std;

#define NMAX 50
const int BAS = 1000;
int A[NMAX+5], B[NMAX+5];
bool dpA[NMAX+5][NMAX+5][600];
bool dpB[NMAX+5][NMAX+5][600];
int sudpA[NMAX+5][NMAX+5];
int sudpB[NMAX+5][NMAX+5];

int main(){
    while (true) {
        int n, m, r, N, M;
        cin >> n >> m >> r;
        if(n == 0) break;
        N = n << 1, M = m << 1;

        for (int i = 0; i < n; i++) cin >> A[i];
        for (int i = n; i < N; i++) A[i] = A[i - n];

        for (int i = 0; i < m; i++) cin >> B[i];
        for (int i = m; i < M; i++) B[i] = B[i - m];

        vector<tuple<int,int,int>> rules;
        int mkaz = 30;
        for (int h = 0; h < r; h++){
            int K;
            cin >> K;
            int pre;
            cin >> pre;
            for (int i = 1; i < K; i++){
                int cur;
                cin >> cur;
                if(i + 1 < K){
                    mkaz++;
                    rules.push_back(make_tuple(pre, cur, mkaz));
                    pre = mkaz;
                } else {
                    int out;
                    cin >> out;
                    rules.push_back(make_tuple(pre, cur, out));
                }
            }
        }

        memset(dpA, 0, sizeof(dpA));
        memset(dpB, 0, sizeof(dpB));
        for (int i = 0; i < N; i++) dpA[i][i+1][ A[i] ] = true;
        for (int i = 0; i < M; i++) dpB[i][i+1][ B[i] ] = true;

        memset(sudpA, 0, sizeof(sudpA));
        memset(sudpB, 0, sizeof(sudpB));
        for (int i = 1; i <= n; i++){
            for (int L = 0; L + i <= N; L++){
                int R = L + i;
                for (size_t j = 0; j < rules.size(); j++){
                    int x, y, z;
                    tie(x, y, z) = rules[j];
                    for (int s = L + 1; s < R; s++)
                        dpA[L][R][z] |= (dpA[L][s][x] && dpA[s][R][y]);
                }
                for (int k = 1; k <= 30; k++)
                    if (dpA[L][R][k]) sudpA[L][R] += (1 << k);
            }
        }
        for (int i = 1; i <= m; i++){
            for (int L = 0; L + i <= M; L++){
                int R = L + i;
                for (size_t j = 0; j < rules.size(); j++){
                    int x, y, z;
                    tie(x, y, z) = rules[j];
                    for (int s = L + 1; s < R; s++)
                        dpB[L][R][z] |= (dpB[L][s][x] && dpB[s][R][y]);
                }
                for (int k = 1; k <= 30; k++)
                    if (dpB[L][R][k]) sudpB[L][R] += (1 << k);
            }
        }

        int ans = -1;
        for (int As = 0; As < n; As++){
            for (int Bs = 0; Bs < m; Bs++){
                int ep[51][51] = {0};
                ep[As][Bs] = BAS;
                for (int Ax = As; Ax < As + n; Ax++){
                    for (int Bx = Bs; Bx < Bs + m; Bx++){
                        if (ep[Ax][Bx] == 0) continue;
                        for (int Ay = Ax + 1; Ay <= As + n; Ay++){
                            for (int By = Bx + 1; By <= Bs + m; By++){
                                if (sudpA[Ax][Ay] & sudpB[Bx][By])
                                    ep[Ay][By] = max(ep[Ay][By], ep[Ax][Bx] + 1);
                            }
                        }
                    }
                }
                ans = max(ans, ep[As+n][Bs+m] - BAS);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 6792
final_rank: 5

code_snippet: // AOJ #1191 Rotate and Rewrite
// 2025.3.30

#include <bits/stdc++.h>
using namespace std;

#define NMAX 50
const int BAS = 10000;
bool dpA[NMAX+5][NMAX+5][600];
bool dpB[NMAX+5][NMAX+5][600];
int sudpA[NMAX+5][NMAX+5];
int sudpB[NMAX+5][NMAX+5];

int main(){
    while (true) {
        int n, m, r, N, M;
        cin >> n >> m >> r;
        if(n == 0) break;
        N = n << 1, M = m << 1;

        int A[NMAX] = {0}, B[NMAX] = {0};
        for (int i = 0; i < n; i++) cin >> A[i];
        for (int i = n; i < N; i++) A[i] = A[i - n];

        for (int i = 0; i < m; i++) cin >> B[i];
        for (int i = m; i < M; i++) B[i] = B[i - m];

        vector<tuple<int,int,int>> rules;
        int mkaz = 30;
        for (int h = 0; h < r; h++){
            int K;
            cin >> K;
            int pre;
            cin >> pre;
            for (int i = 1; i < K; i++){
                int cur;
                cin >> cur;
                if(i + 1 < K){
                    mkaz++;
                    rules.push_back(make_tuple(pre, cur, mkaz));
                    pre = mkaz;
                } else {
                    int out;
                    cin >> out;
                    rules.push_back(make_tuple(pre, cur, out));
                }
            }
        }

        memset(dpA, 0, sizeof(dpA));
        memset(dpB, 0, sizeof(dpB));
        for (int i = 0; i < N; i++) dpA[i][i+1][ A[i] ] = true;
        for (int i = 0; i < M; i++) dpB[i][i+1][ B[i] ] = true;

        memset(sudpA, 0, sizeof(sudpA));
        memset(sudpB, 0, sizeof(sudpB));
        for (int i = 1; i <= n; i++){
            for (int L = 0; L + i <= N; L++){
                int R = L + i;
                for (size_t j = 0; j < rules.size(); j++){
                    int x, y, z;
                    tie(x, y, z) = rules[j];
                    for (int s = L + 1; s < R; s++)
                        dpA[L][R][z] |= (dpA[L][s][x] && dpA[s][R][y]);
                }
                for (int k = 1; k <= 30; k++)
                    if (dpA[L][R][k]) sudpA[L][R] += (1 << k);
            }
        }
        for (int i = 1; i <= m; i++){
            for (int L = 0; L + i <= M; L++){
                int R = L + i;
                for (size_t j = 0; j < rules.size(); j++){
                    int x, y, z;
                    tie(x, y, z) = rules[j];
                    for (int s = L + 1; s < R; s++)
                        dpB[L][R][z] |= (dpB[L][s][x] && dpB[s][R][y]);
                }
                for (int k = 1; k <= 30; k++)
                    if (dpB[L][R][k]) sudpB[L][R] += (1 << k);
            }
        }

        int ans = -1;
        for (int As = 0; As < n; As++){
            for (int Bs = 0; Bs < m; Bs++){
                int ep[51][51] = {0};
                ep[As][Bs] = BAS;
                for (int Ax = As; Ax < As + n; Ax++){
                    for (int Bx = Bs; Bx < Bs + m; Bx++){
                        if (ep[Ax][Bx] == 0) continue;
                        for (int Ay = Ax + 1; Ay <= As + n; Ay++){
                            for (int By = Bx + 1; By <= Bs + m; By++){
                                if (sudpA[Ax][Ay] & sudpB[Bx][By])
                                    ep[Ay][By] = max(ep[Ay][By], ep[Ax][Bx] + 1);
                            }
                        }
                    }
                }
                ans = max(ans, ep[As+n][Bs+m] - BAS);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 230
memory_kb: 6904
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define NMAX 65

int N, M, R;
int a[NMAX], b[NMAX];
int nRule[NMAX];
int fRule[NMAX][15];
int tRule[NMAX];

bool canA[NMAX][NMAX][30], canB[NMAX][NMAX][30];
bool tmpDP[NMAX][NMAX][NMAX][10];

void calccan(int *arr, int orig, bool can[NMAX][NMAX][30]) {
    for (int i = 0; i < NMAX; i++){
        for (int j = 0; j < NMAX; j++){
            for (int k = 0; k < 30; k++) can[i][j][k] = false;
        }
    }
    for (int i = 0; i < NMAX; i++){
        for (int j = 0; j < NMAX; j++){
            for (int r = 0; r < NMAX; r++){
                for (int l = 0; l < 10; l++) tmpDP[i][j][r][l] = (i == j && l == 0);
            }
        }
    }
    for (int i = 0; i < 2 * orig - 1; i++) can[i][i+1][ arr[i] ] = true;

    for (int len = 1; len <= orig; len++){
        for (int l = 0; l + len <= 2 * orig - 1; l++){
            int r = l + len;
            for (int rule = 0; rule < R; rule++){
                for (int j = 1; j <= nRule[rule]; j++){
                    for (int x = l; x < r; x++){
                        if (tmpDP[l][x][rule][j-1] && can[x][r][ fRule[rule][j-1] ])
                            tmpDP[l][r][rule][j] = true;
                    }
                }
            }
            for (int rule = 0; rule < R; rule++)
                if (tmpDP[l][r][rule][ nRule[rule] ]) can[l][r][ tRule[rule] ] = true;
            for (int rule = 0; rule < R; rule++)
                if (can[l][r][ fRule[rule][0] ]) tmpDP[l][r][rule][1] = true;
        }
    }
}

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

    while (true) {
        cin >> N >> M >> R;
        if (N == 0) break;

        for (int i = 0; i < N; i++) cin >> a[i], a[i]--;
        for (int i = 0; i < N; i++) a[i + N] = a[i];
        for (int i = 0; i < M; i++) cin >> b[i], b[i]--;
        for (int i = 0; i < M; i++) b[i + M] = b[i];

        for (int i = 0; i < R; i++){
            int len;
            cin >> len;
            nRule[i] = len;
            for (int j = 0; j < len; j++){
                cin >> fRule[i][j];
                fRule[i][j]--;
            }
            cin >> tRule[i];
            tRule[i]--;
        }

        calccan(a, N, canA);
        calccan(b, M, canB);

        int ans = -1;
        for (int x = 0; x < N; x++){
            for (int y = 0; y < M; y++){
                int dp[26][26];
                for (int i = 0; i < 26; i++){
                    for (int j = 0; j < 26; j++) dp[i][j] = -1;
                }
                dp[0][0] = 0;
                for (int i = 0; i <= N; i++){
                    for (int j = 0; j <= M; j++){
                        if (dp[i][j] < 0) continue;
                        for (int k = 0; k < 30; k++){
                            for (int c = 1; c <= N - i; c++){
                                for (int d = 1; d <= M - j; d++){
                                    if (canA[x + i][x + i + c][k] && canB[y + j][y + j + d][k])
                                        dp[i + c][j + d] = max(dp[i + c][j + d], dp[i][j] + 1);
                                }
                            }
                        }
                    }
                }
                ans = max(ans, dp[N][M]);
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 7140
memory_kb: 6324
final_rank: 18

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T>
bool chmax(T &a, const T &b) {if (a < b) {a = b; return 1;} return 0;}

using ll = long long;

bool is_end = false;

void solve()
{
    ll N, M, R; cin >> N >> M >> R;
    if (N == 0 && M == 0 && R == 0)
    {
        is_end = true;
        return;
    }
    vector<ll> A(N), B(M);
    for (auto &a : A) cin >> a, a--;
    for (auto &b : B) cin >> b, b--;
    vector< pair<ll, vector<ll>> > repl(R);
    for (int i = 0; i < R; ++i)
    {
        int k; cin >> k;
        vector<ll> vec;
        for (int i = 0; i < k; ++i)
        {
            ll x; cin >> x;
            x--;
            vec.emplace_back(x);
        }
        int y; cin >> y;
        y--;
        
        repl[i] = {y, vec};
    }
    
    vector<ll> AA(2 * N), BB(2 * M);
    for (int i = 0; i < N; ++i) AA[i] = AA[N + i] = A[i];
    for (int i = 0; i < M; ++i) BB[i] = BB[M + i] = B[i];
    
    // path[from][char][to] := false / true
    using bs = bitset<60>;
    vector<vector<bs>> pathA(2 * N, vector<bs>(30, 0));
    vector<vector<bs>> pathB(2 * M, vector<bs>(30, 0));
    {
        for (int i = 0; i < 2 * N; ++i)
        {
            int a = AA[i];
            pathA[i][a][i + 1] = true;
        }
        for (int i = 0; i < 2 * M; ++i)
        {
            int b = BB[i];
            pathB[i][b][i+1] = true;
        }
    }
    
    // A
    for (int diff = 2; diff <= N; ++diff)
    {
        for (int from = 0; from < 2 * N; ++from)
        {
            int to = from + diff;
            if (to > 2 * N) break;
            
            for (int r = 0; r < R; ++r)
            {
                auto [c, rule] = repl[r];
                
                bs vec(0), nvec(0);
                vec[from] = true;
                for (auto x : rule)
                {
                    for (int pos = from; pos < to; ++pos)
                    {
                        if (vec[pos]) nvec |= pathA[pos][x];
                    }
                    
                    swap(vec, nvec);
                    nvec = 0;
                }
                if (vec[to]) pathA[from][c][to] = true;
                
            }
        }
    }
    
    // B
    for (int diff = 2; diff <= M; ++diff)
    {
        for (int from = 0; from < 2 * M; ++from)
        {
            int to = from + diff;
            if (to > 2 * M) break;
            
            for (int r = 0; r < R; ++r)
            {
                auto [c, rule] = repl[r];
                
                bs vec(0), nvec(0);
                vec[from] = true;
                for (auto x : rule)
                {
                    for (int pos = from; pos < to; ++pos)
                    {
                        if (vec[pos]) nvec |= pathB[pos][x];
                    }
                    
                    swap(vec, nvec);
                    nvec = 0;
                }
                if (vec[to]) pathB[from][c][to] = true;
                
            }
        }
    }
    
    // for (int from = 0; from < 2 * N; ++from)
    // {
    //     for (int to = 0; to < 2 * N; ++to)
    //     {
    //         for (int c = 0; c < 30; ++c)
    //         {
    //             if (pathA[from][c][to]) cout << from << " " << to << " " << c << endl;
    //         }
    //     }
    // }
    
    // cout << "B" << endl;
    // for (int from = 0; from < 2 * M; ++from)
    // {
    //     for (int to = 0; to < 2 * M; ++to)
    //     {
    //         for (int c = 0; c < 30; ++c)
    //         {
    //             if (pathB[from][c][to]) cout << from << " " << to << " " << c << endl;
    //         }
    //     }
    // }
    
    vector graph(2*N, vector(2*M, vector<pair<int, int>>()));
    for (int sa = 0; sa < 2*N; ++sa)
    {
        for (int sb = 0; sb < 2*M; ++sb)
        {
            for (int ta = sa+1; ta < 2*N; ++ta)
            {
                for (int tb = sb+1; tb < 2*M; ++tb)
                {
                    bool flg = false;
                    for (int c = 0; c < 30; ++c)
                    {
                        if (pathA[sa][c][ta] && pathB[sb][c][tb]) flg = true;
                    }
                    if (flg) graph[sa][sb].push_back({ta, tb});
                    // if (flg) cout << sa << " " << sb << " " << ta << " " << tb << endl;
                }
            }
        }
    }
    
    int res = -1;
    for (int sa = 0; sa < N; ++sa)
    {
        for (int sb = 0; sb < M; ++sb)
        {
            int ta = sa + N, tb = sb + M;
            
            vector dist(2*N, vector<int>(2*M, -1));
            dist[sa][sb] = 0;
            for (int a = sa; a < 2*N; ++a)
            {
                for (int b = sb; b < 2*M; ++b)
                {
                    if(dist[a][b] == -1) continue;
                    for (auto [na, nb] : graph[a][b])
                    {
                        chmax(dist[na][nb], dist[a][b] + 1);
                    }
                }
            }
            
            chmax(res, dist[ta][tb]);
        }
    }
    
    cout << res << endl;
    
    return;
}

int main()
{
    while (!is_end)
    {
        solve();
    }
    
    return 0;
}
accuracy: 1
time_ms: 950
memory_kb: 13588
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;

const int INF = 1012345678;

struct rewrite {
	int len, target;
	vector<int> seq;
};

vector<vector<uint32_t> > get_createable(int N, int K, int L, const vector<int>& A, const vector<rewrite>& R) {
	vector<vector<uint32_t> > dp(N + 1);
	vector<vector<vector<vector<bool> > > > subdp(K);
	for (int i = 0; i < K; i++) {
		subdp[i].resize(N + 1);
		for (int r = 0; r <= N; r++) {
			subdp[i][r].resize(r, vector<bool>(R[i].len + 1));
		}
	}
	for (int r = 1; r <= N; r++) {
		dp[r].resize(r);
		dp[r][r - 1] |= uint32_t(1) << A[r - 1];
		for (int l = r - 1; l >= 0; l--) {
			for (int m = l + 1; m < r; m++) {
				for (int i = 0; i < K; i++) {
					for (int j = 1; j < R[i].len; j++) {
						if (subdp[i][m][l][j] && ((dp[r][m] >> R[i].seq[j]) & 1) == 1) {
							subdp[i][r][l][j + 1] = true;
						}
					}
				}
			}
			for (int i = 0; i < K; i++) {
				if (subdp[i][r][l][R[i].len]) {
					dp[r][l] |= uint32_t(1) << R[i].target;
				}
			}
			for (int i = 0; i < K; i++) {
				if (((dp[r][l] >> R[i].seq[0]) & 1) == 1) {
					subdp[i][r][l][1] = true;
				}
			}
		}
	}
	return dp;
}

int main() {
	while (true) {
		// step #1. input
		int N, M, K;
		cin >> N >> M >> K;
		if (N == 0 && M == 0 && K == 0) {
			break;
		}
		vector<int> A(N), B(M);
		for (int i = 0; i < N; i++) {
			cin >> A[i];
		}
		for (int i = 0; i < M; i++) {
			cin >> B[i];
		}
		vector<rewrite> R(K);
		for (int i = 0; i < K; i++) {
			cin >> R[i].len;
			R[i].seq.resize(R[i].len);
			for (int j = 0; j < R[i].len; j++) {
				cin >> R[i].seq[j];
			}
			cin >> R[i].target;
		}

		// step #2. compression
		vector<int> comp;
		comp.insert(comp.end(), A.begin(), A.end());
		comp.insert(comp.end(), B.begin(), B.end());
		for (int i = 0; i < K; i++) {
			comp.insert(comp.end(), R[i].seq.begin(), R[i].seq.end());
			comp.push_back(R[i].target);
		}
		sort(comp.begin(), comp.end());
		comp.erase(unique(comp.begin(), comp.end()), comp.end());
		for (int i = 0; i < N; i++) {
			A[i] = lower_bound(comp.begin(), comp.end(), A[i]) - comp.begin();
		}
		for (int i = 0; i < M; i++) {
			B[i] = lower_bound(comp.begin(), comp.end(), B[i]) - comp.begin();
		}
		for (int i = 0; i < K; i++) {
			for (int j = 0; j < R[i].len; j++) {
				R[i].seq[j] = lower_bound(comp.begin(), comp.end(), R[i].seq[j]) - comp.begin();
			}
			R[i].target = lower_bound(comp.begin(), comp.end(), R[i].target) - comp.begin();
		}
		int L = comp.size();

		// step #3. compute "creatable" subsequence
		vector<int> DA(N * 2);
		for (int i = 0; i < N * 2; i++) {
			DA[i] = A[i % N];
		}
		vector<int> DB(M * 2);
		for (int i = 0; i < M * 2; i++) {
			DB[i] = B[i % M];
		}
		vector<vector<uint32_t> > f1 = get_createable(N * 2, K, L, DA, R);
		vector<vector<uint32_t> > f2 = get_createable(M * 2, K, L, DB, R);
		int ans = -INF;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				vector<vector<int> > dp(N + 1, vector<int>(M + 1, -INF));
				dp[0][0] = 0;
				for (int k = 0; k <= N; k++) {
					for (int l = 0; l <= M; l++) {
						for (int x = 0; x < k; x++) {
							for (int y = 0; y < l; y++) {
								if (dp[x][y] != -INF && (f1[k + i][x + i] & f2[l + j][y + j]) != 0) {
									dp[k][l] = max(dp[k][l], dp[x][y] + 1);
								}
							}
						}
					}
				}
				if (dp[N][M] != -INF) {
					ans = max(ans, dp[N][M]);
				}
			}
		}
		cout << (ans != -INF ? ans : -1) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 760
memory_kb: 8928
final_rank: 9

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int N, A[69];
int M, B[69];
int R, Y[69]; vector<int> X[69];
bool Temp1[69][69][69];
bool Temp2[69][69];
int dpA[69][69];
int dpB[69][69];
int FinalDP[69][69];

void Initialize() {
	for (int i = 0; i < 69; i++) A[i] = 0;
	for (int i = 0; i < 69; i++) B[i] = 0;
	for (int i = 0; i < 69; i++) Y[i] = 0;
	for (int i = 0; i < 69; i++) X[i].clear();
	for (int i = 0; i < 69; i++) {
		for (int j = 0; j < 69; j++) {
			Temp2[i][j] = false; dpA[i][j] = 0; dpB[i][j] = 0; FinalDP[i][j] = 0;
			for (int k = 0; k < 69; k++) Temp1[i][j][k] = false;
		}
	}
}

int Second(int pos1, int pos2) {
	for (int i = pos1; i <= pos1 + N; i++) {
		for (int j = pos2; j <= pos2 + M; j++) FinalDP[i][j] = -(1 << 30);
	}
	FinalDP[pos1][pos2] = 0;

	// DP Main
	for (int i = pos1; i < pos1 + N; i++) {
		for (int j = pos2; j < pos2 + M; j++) {
			if (FinalDP[i][j] == -(1 << 30)) continue;
			for (int k = i + 1; k <= pos1 + N; k++) {
				for (int l = j + 1; l <= pos2 + M; l++) {
					int v1 = dpA[i % N][k % N];
					int v2 = dpB[j % M][l % M];
					if ((v1 & v2) == 0) continue;
					FinalDP[k][l] = max(FinalDP[k][l], FinalDP[i][j] + 1);
				}
			}
		}
	}

	// Return
	return FinalDP[pos1 + N][pos2 + M];
}

bool solve_sub(int cl, int cr, int idx, int sz) {
	for (int i = 0; i <= X[idx].size(); i++) {
		for (int j = cl; j <= cr; j++) Temp2[i][j] = false;
	}
	Temp2[0][cl] = true;

	// DP Sub
	for (int i = 0; i < X[idx].size(); i++) {
		for (int j = cl; j < cr; j++) {
			if (Temp2[i][j] == false) continue;
			for (int k = j + 1; k <= cr; k++) {
				int v1 = j % sz;
				int v2 = k % sz;
				if (Temp1[v1][v2][X[idx][i]] == true) Temp2[i + 1][k] = true;
			}
		}
	}
	return Temp2[X[idx].size()][cr];
}

void solve(vector<int> List) {
	// Init Part
	for (int i = 0; i < List.size(); i++) {
		for (int j = 0; j < List.size(); j++) {
			for (int k = 1; k <= 30; k++) Temp1[i][j][k] = false;
		}
	}
	for (int i = 0; i < List.size(); i++) Temp1[i][(i + 1) % List.size()][List[i]] = true;

	// Main Part
	for (int haba = 2; haba <= List.size(); haba++) {
		for (int l = 0; l < List.size(); l++) {
			int r = l + haba;
			for (int i = 0; i < R; i++) {
				bool ret = solve_sub(l, r, i, List.size());
				if (ret == true) Temp1[l][r % List.size()][Y[i]] = true;
			}
		}
	}
}

int main() {
	while (true) {
		Initialize();

		// Step 1. Input
		cin >> N >> M >> R; if (N + M + R == 0) break;
		for (int i = 0; i < N; i++) cin >> A[i];
		for (int i = 0; i < M; i++) cin >> B[i];
		for (int i = 0; i < R; i++) {
			int k; cin >> k;
			X[i] = vector<int>(k, 0);
			for (int j = 0; j < k; j++) cin >> X[i][j];
			cin >> Y[i];
		}

		// Step 2. DP Part 1
		vector<int> ListA; for (int i = 0; i < N; i++) ListA.push_back(A[i]);
		vector<int> ListB; for (int i = 0; i < M; i++) ListB.push_back(B[i]);
		solve(ListA);
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < N; j++) {
				for (int k = 1; k <= 30; k++) {
					if (Temp1[i][j][k] == true) dpA[i][j] += (1 << k);
				}
			}
		}
		solve(ListB);
		for (int i = 0; i < M; i++) {
			for (int j = 0; j < M; j++) {
				for (int k = 1; k <= 30; k++) {
					if (Temp1[i][j][k] == true) dpB[i][j] += (1 << k);
				}
			}
		}

		// Step 3. DP Part 2
		int Answer = -(1 << 30);
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				int ret = Second(i, j);
				Answer = max(Answer, ret);
			}
		}

		// Step 4. Output
		if (Answer == -(1 << 30)) cout << "-1" << endl;
		else cout << Answer << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 900
memory_kb: 3696
final_rank: 3

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#define rep(i, s, n) for (int i = int(s); i < int(n); i++)
#define rrep(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)
#define all(v) v.begin(), v.end()

using ll = long long;
using ld = long double;
using ull = unsigned long long;

template <class T> bool chmin(T &a, T b) {
    if (a <= b) return false;
    a = b;
    return true;
}

template <class T> bool chmax(T &a, T b) {
    if (a >= b) return false;
    a = b;
    return true;
}

#define debug(...)                                                     \
    std::cerr << "LINE: " << __LINE__ << " [" << #__VA_ARGS__ << "]:", \
        debug_out(__VA_ARGS__)

void debug_out() {
    std::cerr << std::endl;
}

template <typename Head, typename... Tail> void debug_out(Head h, Tail... t) {
    std::cerr << " " << h;
    if (sizeof...(t) > 0) std::cerr << ",";
    debug_out(t...);
}

template <typename T1, typename T2>
std::ostream &operator<<(std::ostream &os, const std::pair<T1, T2> &pa) {
    return os << pa.first << " " << pa.second;
}

int n, m, rs;
std::vector<std::vector<int>> a;
std::vector<std::vector<int>> xs;
std::vector<int> ys;

bool dp[2][60][60][40];
bool edp[2][60][60][60][20];

void init() {
    a.clear();
    xs.clear();
    ys.clear();
    a.resize(2);
    a[0].resize(n);
    a[1].resize(m);
    xs.resize(rs);
    ys.resize(rs);
    rep(i, 0, 2) rep(j, 0, 60) rep(k, 0, 60) {
        rep(l, 0, 40) {
            dp[i][j][k][l] = false;
        }
        rep(l, 0, 60) {
            rep(x, 0, 20) {
                edp[i][j][k][l][x] = false;
            }
        }
    }
}

void calc() {
    int idx = 0;
    rep(i, 0, n) rep(j, 0, rs) edp[idx][i][i][j][0] = true;
    rep(i, 0, 2 * n) {
        dp[idx][i][i + 1][a[idx][i]] = true;
    }
    rep(len, 1, n + 1) {
        for (int l = 0; l + len < 2 * n; l++) {
            int r = l + len;
            rep(i, 0, rs) {
                rep(j, 1, int(xs[i].size()) + 1) {
                    rep(k, l + 1, r) edp[idx][l][r][i][j] |=
                        edp[idx][l][k][i][j - 1] & dp[idx][k][r][xs[i][j - 1]];
                }
            }
            rep(i, 0, rs) {
                if (edp[idx][l][r][i][xs[i].size()])
                    dp[idx][l][r][ys[i]] = true;
            }
            rep(i, 0, rs) {
                if (dp[idx][l][r][xs[i][0]]) edp[idx][l][r][i][1] = true;
            }
        }
    }
    idx = 1;
    rep(i, 0, m) rep(j, 0, rs) edp[idx][i][i][j][0] = true;
    rep(i, 0, 2 * m) {
        dp[idx][i][i + 1][a[idx][i]] = true;
    }
    rep(len, 1, m + 1) {
        for (int l = 0; l + len < 2 * m; l++) {
            int r = l + len;
            rep(i, 0, rs) {
                rep(j, 1, int(xs[i].size()) + 1) {
                    rep(k, l + 1, r) edp[idx][l][r][i][j] |=
                        edp[idx][l][k][i][j - 1] & dp[idx][k][r][xs[i][j - 1]];
                }
            }
            rep(i, 0, rs) {
                if (edp[idx][l][r][i][xs[i].size()])
                    dp[idx][l][r][ys[i]] = true;
            }
            rep(i, 0, rs) {
                if (dp[idx][l][r][xs[i][0]]) edp[idx][l][r][i][1] = true;
            }
        }
    }
}

bool solve() {
    std::cin >> n >> m >> rs;
    if (n == 0 && m == 0 && rs == 0) return false;
    init();
    rep(i, 0, n) {
        std::cin >> a[0][i];
    }
    rep(i, 0, n) a[0].emplace_back(a[0][i]);
    rep(i, 0, m) {
        std::cin >> a[1][i];
    }
    rep(i, 0, m) a[1].emplace_back(a[1][i]);
    rep(i, 0, rs) {
        int k;
        std::cin >> k;
        xs[i].resize(k);
        rep(j, 0, k) {
            std::cin >> xs[i][j];
        }
        std::cin >> ys[i];
    }
    calc();
    int ans = -1;
    rep(la, 0, n) {
        rep(lb, 0, m) {
            std::vector gdp(n + 1, std::vector<int>(m + 1, -1));
            gdp[0][0] = 0;
            rep(ra, 0, n) {
                rep(rb, 0, m) {
                    if (gdp[ra][rb] == -1) continue;
                    rep(raa, ra + 1, n + 1) {
                        rep(rbb, rb + 1, m + 1) {
                            rep(c, 0, 40) {
                                if(dp[0][la + ra][la + raa][c] && dp[1][lb + rb][lb + rbb][c]) {
                                    chmax(gdp[raa][rbb], gdp[ra][rb] + 1);
                                }
                            }
                        }
                    }
                }
            }
            chmax(ans, gdp[n][m]);
        }
    }
    std::cout << ans << '\n';
    return true;
}

int main() {
    while (solve())
        ;
}
accuracy: 1
time_ms: 7110
memory_kb: 11920
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (int i = (int)(s); i < (int)(t); ++i)
#define revrep(i, t, s) for (int i = (int)(t)-1; i >= (int)(s); --i)
#define all(x) begin(x), end(x)
template <typename T>
bool chmax(T& a, const T& b) {
    return a < b ? (a = b, 1) : 0;
}
template <typename T>
bool chmin(T& a, const T& b) {
    return a > b ? (a = b, 1) : 0;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    const int X = 31;

    while (true) {
        int n, m, r;
        cin >> n >> m >> r;
        if (n == 0) break;
        vector<int> A(2 * n), B(2 * m);
        rep(i, 0, n) {
            int x;
            cin >> x;
            A[i] = A[n + i] = x;
        }
        rep(i, 0, m) {
            int x;
            cin >> x;
            B[i] = B[m + i] = x;
        }
        vector<vector<vector<int>>> rules(X);
        rep(_, 0, r) {
            int k;
            cin >> k;
            vector<int> xs(k);
            for (auto& x : xs) cin >> x;
            int y;
            cin >> y;
            rules[y].push_back(xs);
        }

        auto calc = [&](vector<int> A) {
            int n = A.size();
            vector dp(n, vector<int>(n + 1));
            rep(i, 0, n) { dp[i][i + 1] = 1 << A[i]; }
            rep(l, 2, n + 1) rep(i, 0, n - l + 1) {
                int j = i + l;

                rep(c, 0, X) for (auto& xs : rules[c]) {
                    int k = xs.size();
                    vector f(l + 1, vector<bool>(k + 1));

                    f[0][0] = true;

                    rep(s, 0, l) rep(t, s + 1, l + 1) {
                        rep(u, 0, k) {
                            if (f[s][u] && (dp[i + s][i + t] >> xs[u] & 1)) {
                                f[t][u + 1] = true;
                            }
                        }
                    }

                    if (f[l][k]) {
                        dp[i][j] |= 1 << c;
                    }
                }
            }
            return dp;
        };

        auto dpA = calc(A);
        auto dpB = calc(B);

        int ans = -1;

        rep(shiftA, 0, n) rep(shiftB, 0, m) {
            vector g(n + 1, vector<int>(m + 1, -1e9));
            g[0][0] = 0;
            rep(i, 1, n + 1) rep(j, 1, m + 1) {
                rep(a, 0, i) rep(b, 0, j) {
                    if (dpA[shiftA + a][shiftA + i] &
                        dpB[shiftB + b][shiftB + j]) {
                        chmax(g[i][j], g[a][b] + 1);
                    }
                }
            }
            chmax(ans, g[n][m]);
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 2420
memory_kb: 3524
final_rank: 10

code_snippet: #include "bits/stdc++.h"
using namespace std;
using namespace std::chrono;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
#define REP(i, n) for(int i = 0;i < (n);i++)
/*cout<<fixed<<setprecision(20);cin.tie(0);ios::sync_with_stdio(false);*/
const int mod=1000000007;
const llint inf=2.19e15+1;
const long double pai=3.141592653589793238462643383279502884197;
const long double eps=1e-10;
template <class T,class U>bool chmin(T& a,U b){if(a>b){a=b;return true;}return false;}
template <class T,class U>bool chmax(T& a,U b){if(a<b){a=b;return true;}return false;}
llint gcd(llint a,llint b){if(a%b==0){return b;}else return gcd(b,a%b);}
llint lcm(llint a,llint b){if(a==0){return b;}return a/gcd(a,b)*b;}
template<class T> void SO(T& ve){sort(ve.begin(),ve.end());}
template<class T> void REV(T& ve){reverse(ve.begin(),ve.end());}
template<class T>int LBI(const vector<T>&ar,T in){return lower_bound(ar.begin(),ar.end(),in)-ar.begin();}
template<class T>int UBI(const vector<T>&ar,T in){return upper_bound(ar.begin(),ar.end(),in)-ar.begin();}

int main(void){
	while(-1){
		int n,m,r,h,i,j,k;
		cin>>n>>m>>r;
		if(n==0){return 0;}
		int A[50]={};
		int B[50]={};
		for(i=0;i<n;i++){cin>>A[i];}
		for(i=n;i<n+n;i++){A[i]=A[i-n];}
		for(i=0;i<m;i++){cin>>B[i];}
		for(i=m;i<m+m;i++){B[i]=B[i-m];}
		
		
		vector<tuple<int,int,int>>rules;
		int mkaz=30;
		for(h=0;h<r;h++){
			int Ka;cin>>Ka;
			int mae;cin>>mae;
			for(i=1;i<Ka;i++){
				int now;cin>>now;
				if(i+1<Ka){
					mkaz++;
					rules.pub(mt(mae,now,mkaz));
					mae=mkaz;
				}else{
					int ruy;cin>>ruy;
					rules.pub(mt(mae,now,ruy));
				}
			}
		}
		
		static bool dpA[51][51][600]={};
		static bool dpB[51][51][600]={};
		for(i=0;i<=50;i++){
			for(j=0;j<=50;j++){
				for(k=0;k<600;k++){
					dpA[i][j][k]=false;
					dpB[i][j][k]=false;
				}
			}
		}
		//R,文字種類 の Lbit目をみる
		for(i=0;i<n+n;i++){
			dpA[i][i+1][A[i]]=1;
		}
		for(i=0;i<m+m;i++){
			dpB[i][i+1][B[i]]=1;
		}
		int sudpA[51][51]={};
		int sudpB[51][51]={};
		for(i=1;i<=n;i++){
			for(int L=0;L+i<=n+n;L++){
				int R=L+i;
				for(j=0;j<rules.size();j++){
					int x,y,z;
					tie(x,y,z)=rules[j];
					for(int s=L+1;s<R;s++){
						dpA[L][R][z]|=dpA[L][s][x]&&dpA[s][R][y];
					}
				}
				for(k=1;k<=30;k++){
					if(dpA[L][R][k]){sudpA[L][R]+=(1<<k);}
				}
				//cerr<<"sudpA["<<L<<"]["<<R<<"]="<<sudpA[L][R]<<endl;
			}
		}
		for(i=1;i<=m;i++){
			for(int L=0;L+i<=m+m;L++){
				int R=L+i;
				for(j=0;j<rules.size();j++){
					int x,y,z;
					tie(x,y,z)=rules[j];
					for(int s=L+1;s<R;s++){
						dpB[L][R][z]|=dpB[L][s][x]&&dpB[s][R][y];
					}
				}
				for(k=1;k<=30;k++){
					if(dpB[L][R][k]){sudpB[L][R]+=(1<<k);}
				}
				//cerr<<"sudpB["<<L<<"]["<<R<<"]="<<sudpB[L][R]<<endl;
			}
		}
		
		
		//次 対応を走査
		int ans=-1;
		for(int As=0;As<n;As++){
			for(int Bs=0;Bs<m;Bs++){
				int ep[51][51]={};
				ep[As][Bs]=mod;
				for(int Ax=As;Ax<As+n;Ax++){
					for(int Bx=Bs;Bx<Bs+m;Bx++){
						if(ep[Ax][Bx]==0){continue;}
						//ここから遷移する
						for(int Ay=Ax+1;Ay<=As+n;Ay++){
							for(int By=Bx+1;By<=Bs+m;By++){
								if(sudpA[Ax][Ay]&sudpB[Bx][By]){
									chmax(ep[Ay][By],ep[Ax][Bx]+1);
								}
							}
						}
					}
				}
				chmax(ans,ep[As+n][Bs+m]-mod);
			}
		}
		cout<<ans<<endl;
	}
	return 0;
}

/*
3 3 3
1 2 3
4 5 6
2 1 2 5
2 6 4 3
2 5 3 1

3 3 2
1 1 1
2 2 1
2 1 1 2
2 2 2 1

7 1 2
1 1 2 1 4 1 2
4
3 1 4 1 4
3 2 4 2 4

16 14 5
2 1 2 2 1 3 2 1 3 2 2 1 1 3 1 2
2 1 3 1 1 2 3 1 2 2 2 2 1 3
2 3 1 3
3 2 2 2 1
3 2 2 1 2
3 1 2 2 2
4 2 1 2 2 2

0 0 0
*/
accuracy: 1
time_ms: 370
memory_kb: 6428
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=1000000007,MAX=35,INF=1<<29;

bool sub1[MAX][MAX][MAX];
bool sub2[MAX][MAX][MAX];
bool can[MAX][MAX];
bool match[MAX][MAX][MAX][MAX];
int dp[MAX*2][MAX*2];

int main(){
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    while(1){
        int N,M,K;cin>>N>>M>>K;
        if(N==0) break;
        vector<int> A(N),B(M);
        for(int i=0;i<N;i++){
            cin>>A[i];A[i]--;
        }
        for(int i=0;i<N;i++) A.push_back(A[i]);
        for(int i=0;i<M;i++){
            cin>>B[i];B[i]--;
        }
        for(int i=0;i<M;i++) B.push_back(B[i]);
        vector<vector<int>> S(K);vector<int> T(K);
        for(int i=0;i<K;i++){
            int x;cin>>x;
            S[i].resize(x);
            for(int j=0;j<x;j++){
                cin>>S[i][j];S[i][j]--;
            }
            cin>>T[i];T[i]--;
        }
        memset(sub1,0,sizeof(sub1));
        memset(sub2,0,sizeof(sub2));
        
        for(int len=1;len<=N;len++){
            for(int l=0;l<N;l++){
                int r=(l+len-1)%N;
                if(len==1) sub1[l][r][A[l]]=true;
                else{
                    for(int k=0;k<K;k++){
                        memset(can,0,sizeof(can));
                        can[l][0]=true;
                        for(int i=l;i<l+len;i++){
                            for(int j=si(S[k])-1;j>=0;j--){
                                if(!can[i%N][j]) continue;
                                for(int to=i+1;to<=l+len;to++){
                                    if(sub1[i%N][(to-1)%N][S[k][j]]) can[to%N][j+1]=true;
                                }
                            }
                        }
                        if(can[(l+len)%N][si(S[k])]) sub1[l][r][T[k]]=true;
                    }
                }
            }
        }
        
        for(int len=1;len<=M;len++){
            for(int l=0;l<M;l++){
                int r=(l+len-1)%M;
                if(len==1) sub2[l][r][B[l]]=true;
                else{
                    for(int k=0;k<K;k++){
                        memset(can,0,sizeof(can));
                        can[l][0]=true;
                        for(int i=l;i<l+len;i++){
                            for(int j=si(S[k])-1;j>=0;j--){
                                if(!can[i%M][j]) continue;
                                for(int to=i+1;to<=l+len;to++){
                                    if(sub2[i%M][(to-1)%M][S[k][j]]) can[to%M][j+1]=true;
                                }
                            }
                        }
                        if(can[(l+len)%M][si(S[k])]) sub2[l][r][T[k]]=true;
                    }
                }
            }
        }
        
        memset(match,0,sizeof(match));
        for(int l1=0;l1<N;l1++){
            for(int r1=0;r1<N;r1++){
                for(int l2=0;l2<M;l2++){
                    for(int r2=0;r2<M;r2++){
                        for(int k=0;k<30;k++){
                            if(sub1[l1][r1][k]&&sub2[l2][r2][k]) match[l1][r1][l2][r2]=true;
                        }
                    }
                }
            }
        }
        
        int ans=-1;
        
        for(int l1=0;l1<N;l1++){
            for(int l2=0;l2<M;l2++){
                for(int i=0;i<=2*N;i++) for(int j=0;j<=2*M;j++) dp[i][j]=-INF;
                dp[l1][l2]=0;
                for(int i=l1;i<l1+N;i++){
                    for(int j=l2;j<l2+M;j++){
                        if(dp[i][j]==-INF) continue;
                        for(int a=i+1;a<=l1+N;a++){
                            for(int b=j+1;b<=l2+M;b++){
                                if(match[i%N][(a-1)%N][j%M][(b-1)%M]) chmax(dp[a][b],dp[i][j]+1);
                            }
                        }
                    }
                }
                chmax(ans,dp[l1+N][l2+M]);
            }
        }
        
        cout<<ans<<endl;
    }
}
accuracy: 1
time_ms: 960
memory_kb: 4972
final_rank: 8

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

int main() {
    while(1) {
        INT(n, m, r);
        if(!n) exit(0);
        VEC(int, a, n);
        VEC(int, b, m);
        rep(i, n) a[i]--;
        rep(i, m) b[i]--;

        struct S {
            vi v;
            vvc<int> match;
            S(vi a) : v(a) { match = vvc<int>(si(a) + 1, vi(si(a) + 1)); }
            S() = default;
        };

        vector<S> A, B;
        rep(i, n) {
            A.eb(a);
            rotate(begin(a), begin(a) + 1, end(a));
        }
        rep(i, m) {
            B.eb(b);
            rotate(begin(b), begin(b) + 1, end(b));
        }

        vector<pair<int, vi>> R;
        rep(i, r) {
            INT(k);
            VEC(int, x, k);
            rep(i, k) x[i]--;
            INT(y);
            y--;
            R.eb(y, x);
        }

        vv(int, DP, 30, 30);
        auto calc = [&](S &s) {
            auto &dp = s.match;
            int n = si(s.v);
            rep2(d, 1, n) {
                rep(i, n) {
                    int j = i + d;
                    if(j > n) break;
                    if(d == 1) {
                        dp[i][j] = 1 << s.v[i];
                        continue;
                    }
                    for(auto &[y, x] : R) {
                        if(dp[i][j] >> y & 1) continue;
                        int k = si(x);
                        rep(i, d + 1) rep(j, k + 1) DP[i][j] = 0;
                        DP[0][0] = 1;
                        rep(ii, d) rep(jj, k) {
                            if(!DP[ii][jj]) continue;
                            rep2(to, ii + 1, d) {
                                int l = i + ii;
                                int r = i + to;
                                if(dp[l][r] >> x[jj] & 1) DP[to][jj + 1] = true;
                            }
                        }
                        if(DP[d][k]) dp[i][j] |= 1 << y;
                    }
                }
            }
        };
        each(e, A) calc(e);
        each(e, B) calc(e);

        int ma = -1;
        each(a, A) each(b, B) {
            rep(i, n + 1) rep(j, m + 1) DP[i][j] = -inf<int>;
            DP[0][0] = 0;
            auto &x = a.match, &y = b.match;
            rep(i, n) rep(j, m) {
                if(DP[i][j] < 0) continue;
                rep2(ii, i + 1, n) rep2(jj, j + 1, m) {
                    if(x[i][ii] & y[j][jj]) chmax(DP[ii][jj], DP[i][j] + 1);
                }
            }
            chmax(ma, DP[n][m]);
        }
        OUT(ma);
    }
}
accuracy: 1
time_ms: 390
memory_kb: 3648
final_rank: 2

code_snippet: #line 1 "other-workspace\\icpc\\f.cc"
#include <bits/stdc++.h>

using namespace std;

void chgr(int &x, int y) {
  if (x < y) x = y;
}

int main() {
  constexpr auto sigma = 30;

  int n, m, r;

  while (1) {
    cin >> n >> m >> r;
    if (!n and !m and !r) break;

    vector<int> a(n), b(m);
    for (auto &&x : a) {
      cin >> x;
      --x;
    }
    for (auto &&x : b) {
      cin >> x;
      --x;
    }

    vector<vector<vector<int>>> trf(sigma);

    while (r--) {
      int k;
      cin >> k;
      vector<int> src;
      int dst;
      while (k--) {
        cin >> src.emplace_back();
        --src.back();
      }
      cin >> dst;
      --dst;
      trf[dst].emplace_back(src);
    }

    auto pre = [&](vector<int> v) {
      vector dp(v.size() + 1, vector<int>(v.size() + 1));

      for (auto j = 1; j <= v.size(); ++j) {
        dp[j - 1][j] = 1 << v[j - 1];

        for (auto i = j - 1; i--;) {
          for (auto c = 0; c < sigma; ++c) {
            // make [i, j) into c!
            auto succ = 0;

            for (auto &&src : trf[c]) {
              vector able(j + 1, vector<int>(src.size() + 1));
              able[i][0] = 1;

              for (auto l = i; l < j; l++) {
                for (auto k = 0; k < src.size(); k++) {
                  if (!able[l][k]) continue;

                  for (auto r = l + 1; r <= j; ++r) {
                    if (dp[l][r] >> src[k] & 1) {
                      able[r][k + 1] = 1;
                    }
                  }
                }
              }

              if (able.back().back()) {
                succ = 1;
              }
            }

            dp[i][j] |= succ << c;
          }
        }
      }

      return dp;
    };

    vector<vector<vector<int>>> dpa, dpb;

    for (auto t = 0; t < n; t++) {
      dpa.emplace_back(pre(a));
      rotate(begin(a), begin(a) + 1, end(a));
    }

    for (auto t = 0; t < m; t++) {
      dpb.emplace_back(pre(b));
      rotate(begin(b), begin(b) + 1, end(b));
    }

    auto answer = -1;

    for (auto &&ap : dpa) {
      for (auto &&bp : dpb) {
        vector dp(n + 1, vector(m + 1, -1));
        dp[0][0] = 0;

        for (auto il = 0; il < n; il++) {
          for (auto jl = 0; jl < m; jl++) {
            if (~dp[il][jl]) {
              for (auto ir = il + 1; ir <= n; ir++) {
                for (auto jr = jl + 1; jr <= m; jr++) {
                  // A: [il, ir)
                  // B: [jl, jr)
                  if (ap[il][ir] & bp[jl][jr]) {
                    chgr(dp[ir][jr], dp[il][jl] + 1);
                  }
                }
              }
            }
          }
        }

        chgr(answer, dp[n][m]);
      }
    }

    cout << answer << "\n";
  }
}
accuracy: 1
time_ms: 3750
memory_kb: 3608
final_rank: 13

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

int main() {
    while(1) {
        INT(n, m, r);
        if(!n) exit(0);
        VEC(int, a, n);
        VEC(int, b, m);
        rep(i, n) a[i]--;
        rep(i, m) b[i]--;

        struct S {
            vi v;
            vvc<int> match;
            S(vi a) : v(a) { match = vvc<int>(si(a) + 1, vi(si(a) + 1)); }
            S() = default;
        };

        vector<S> A, B;
        rep(i, n) {
            A.eb(a);
            rotate(begin(a), begin(a) + 1, end(a));
        }
        rep(i, m) {
            B.eb(b);
            rotate(begin(b), begin(b) + 1, end(b));
        }

        vector<pair<int, vi>> R;
        rep(i, r) {
            INT(k);
            VEC(int, x, k);
            rep(i, k) x[i]--;
            INT(y);
            y--;
            R.eb(y, x);
        }

        vv(int, DP, 30, 30);
        auto calc = [&](S &s) {
            auto &dp = s.match;
            int n = si(s.v);
            rep2(d, 1, n) {
                rep(i, n) {
                    int j = i + d;
                    if(j > n) break;
                    if(d == 1) {
                        dp[i][j] = 1 << s.v[i];
                        continue;
                    }
                    for(auto &[y, x] : R) {
                        if(dp[i][j] >> y & 1) continue;
                        int k = si(x);
                        rep(i, d + 1) rep(j, k + 1) DP[i][j] = 0;
                        DP[0][0] = 1;
                        rep(ii, d) rep(jj, k) {
                            if(!DP[ii][jj]) continue;
                            rep2(to, ii + 1, d) {
                                int l = i + ii;
                                int r = i + to;
                                if(dp[l][r] >> x[jj] & 1) DP[to][jj + 1] = true;
                            }
                        }
                        if(DP[d][k]) dp[i][j] |= 1 << y;
                    }
                }
            }
        };
        each(e, A) calc(e);
        each(e, B) calc(e);

        int ma = -1;
        each(a, A) each(b, B) {
            rep(i, n + 1) rep(j, m + 1) DP[i][j] = -inf<int>;
            DP[0][0] = 0;
            auto &x = a.match, &y = b.match;
            rep(i, n) rep(j, m) {
                if(DP[i][j] < 0) continue;
                rep2(ii, i + 1, n) rep2(jj, j + 1, m) {
                    if(x[i][ii] & y[j][jj]) chmax(DP[ii][jj], DP[i][j] + 1);
                }
            }
            chmax(ma, DP[n][m]);
        }
        OUT(ma);
    }
}
accuracy: 1
time_ms: 390
memory_kb: 3596
final_rank: 1

code_snippet: #pragma region Macros
#pragma comment(linker, "/stack:200000000")
// #pragma GCC optimize("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2,tune=native")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,fma,abm,mmx,avx,avx2")
// #pragma GCC target("avx2")
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
#define ll long long
using ld = long double;
#define rep2(i, a, b) for(ll i = (a); i <= (b); i++)
#define rep3(i, a, b) for(ll i = (a); i >= (b); --i)
#define rep(i, n) for(ll i = 0; i < n; ++i)
#define each(i, a) for(auto &&i : a)
#define pii pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define eb emplace_back
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define vpll vector<pll>
#define overload2(_1, _2, name, ...) name
#define vec(type, name, ...) vector<type> name(__VA_ARGS__)
#define VEC(type, name, size)                                                                                                                                  \
    vector<type> name(size);                                                                                                                                   \
    IN(name)
#define VEC2(type, name1, name2, size)                                                                                                                         \
    vector<type> name1(size), name2(size);                                                                                                                     \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i])
#define VEC3(type, name1, name2, name3, size)                                                                                                                  \
    vector<type> name1(size), name2(size), name3(size);                                                                                                        \
    for(int i = 0; i < size; i++) IN(name1[i], name2[i], name3[i])
#define vv(type, name, h, ...) vector<vector<type>> name(h, vector<type>(__VA_ARGS__))
#define VV(type, name, h, w)                                                                                                                                   \
    vector<vector<type>> name(h, vector<type>(w));                                                                                                             \
    IN(name)
#define vvv(type, name, h, w, ...) vector<vector<vector<type>>> name(h, vector<vector<type>>(w, vector<type>(__VA_ARGS__)))
#define vvvv(type, name, a, b, c, ...)                                                                                                                         \
    vector<vector<vector<vector<type>>>> name(a, vector<vector<vector<type>>>(b, vector<vector<type>>(c, vector<type>(__VA_ARGS__))))
#define mt make_tuple
#define fi first
#define se second
#define all(c) begin(c), end(c)
#define rall(c) rbegin(c), rend(c)
#define SORT(v) sort(all(v))
#define REV(v) reverse(all(v))
template <class T = ll, class S> T SUM(const S &v) { return accumulate(all(v), T(0)); }
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define lb(c, x) distance((c).begin(), lower_bound(all(c), (x)))
#define ub(c, x) distance((c).begin(), upper_bound(all(c), (x)))
using namespace std;
constexpr pii dx4[4] = {pii{1, 0}, pii{0, 1}, pii{-1, 0}, pii{0, -1}};
constexpr pii dx8[8] = {{1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}};
const string YESNO[2] = {"NO", "YES"};
const string YesNo[2] = {"No", "Yes"};
const string yesno[2] = {"no", "yes"};
void YES(bool t = 1) { cout << YESNO[t] << endl; }
void NO(bool t = 1) { YES(!t); }
void Yes(bool t = 1) { cout << YesNo[t] << endl; }
void No(bool t = 1) { Yes(!t); }
void yes(bool t = 1) { cout << yesno[t] << endl; }
void no(bool t = 1) { yes(!t); }
template <class T> using vc = vector<T>;
template <class T> using vvc = vector<vc<T>>;
template <class T> using vvvc = vector<vvc<T>>;
template <class T> using vvvvc = vector<vvvc<T>>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
#define si(c) (int)(c).size()
#define INT(...)                                                                                                                                               \
    int __VA_ARGS__;                                                                                                                                           \
    IN(__VA_ARGS__)
#define LL(...)                                                                                                                                                \
    ll __VA_ARGS__;                                                                                                                                            \
    IN(__VA_ARGS__)
#define STR(...)                                                                                                                                               \
    string __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
#define CHR(...)                                                                                                                                               \
    char __VA_ARGS__;                                                                                                                                          \
    IN(__VA_ARGS__)
#define DBL(...)                                                                                                                                               \
    double __VA_ARGS__;                                                                                                                                        \
    IN(__VA_ARGS__)
int scan() { return getchar(); }
void scan(int &a) { cin >> a; }
void scan(long long &a) { cin >> a; }
void scan(char &a) { cin >> a; }
void scan(double &a) { cin >> a; }
void scan(string &a) { cin >> a; }
template <class T, class S> void scan(pair<T, S> &p) { scan(p.first), scan(p.second); }
template <class T> void scan(vector<T> &);
template <class T> void scan(vector<T> &a) {
    for(auto &i : a) scan(i);
}
template <class T> void scan(T &a) { cin >> a; }
void IN() {}
template <class Head, class... Tail> void IN(Head &head, Tail &...tail) {
    scan(head);
    IN(tail...);
}

template <class T, class S> inline bool chmax(T &a, const S &b) { return (a < b ? a = b, 1 : 0); }
template <class T, class S> inline bool chmin(T &a, const S &b) { return (a > b ? a = b, 1 : 0); }
vi iota(int n) {
    vi a(n);
    iota(all(a), 0);
    return a;
}
template <typename T> vi iota(vector<T> &a, bool greater = false) {
    vi res(a.size());
    iota(all(res), 0);
    sort(all(res), [&](int i, int j) {
        if(greater) return a[i] > a[j];
        return a[i] < a[j];
    });
    return res;
}
#define UNIQUE(x) sort(all(x)), x.erase(unique(all(x)), x.end())

template <class T> T ceil(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? (x + y - 1) / y : x / y);
}

template <class T> T floor(T x, T y) {
    assert(y >= 1);
    return (x > 0 ? x / y : (x + y - 1) / y);
}
template <class T> T POW(T x, int n) {
    T res = 1;
    for(; n; n >>= 1, x *= x)
        if(n & 1) res *= x;
    return res;
}
template <class T, class S> T POW(T x, S n, const ll &mod) {
    T res = 1;
    for(; n; n >>= 1, x = x * x % mod)
        if(n & 1) res = res * x % mod;
    return res;
}
vector<pll> factor(ll x) {
    vector<pll> ans;
    for(ll i = 2; i * i <= x; i++)
        if(x % i == 0) {
            ans.push_back({i, 1});
            while((x /= i) % i == 0) ans.back().second++;
        }
    if(x != 1) ans.push_back({x, 1});
    return ans;
}
template <class T> vector<T> divisor(T x) {
    vector<T> ans;
    for(T i = 1; i * i <= x; i++)
        if(x % i == 0) {
            ans.pb(i);
            if(i * i != x) ans.pb(x / i);
        }
    return ans;
}
template <typename T> void zip(vector<T> &x) {
    vector<T> y = x;
    UNIQUE(y);
    for(int i = 0; i < x.size(); ++i) { x[i] = lb(y, x[i]); }
}
template <class S> void fold_in(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void fold_in(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto e : a) v.emplace_back(e);
    fold_in(v, tail...);
}
template <class S> void renumber(vector<S> &v) {}
template <typename Head, typename... Tail, class S> void renumber(vector<S> &v, Head &&a, Tail &&...tail) {
    for(auto &&e : a) e = lb(v, e);
    renumber(v, tail...);
}
template <class S, class... Args> vector<S> zip(vector<S> &head, Args &&...args) {
    vector<S> v;
    fold_in(v, head, args...);
    sort(all(v)), v.erase(unique(all(v)), v.end());
    renumber(v, head, args...);
    return v;
}

// x in [l, r)
template <class T, class S> bool inc(const T &x, const S &l, const S &r) { return l <= x and x < r; }
// (a, b) in [lx, rx) * [ly, ry)
template <class T, class S> bool inc(const pair<T, T> &x, const S &lx, const S &ly, const S &rx, const S &ry) { return inc(x.fi, lx, rx) && inc(x.se, ly, ry); }

constexpr ll ten(int n) { return n == 0 ? 1 : ten(n - 1) * 10; }
// bit 演算系
ll pow2(int i) { return 1LL << i; }
int topbit(signed t) { return t == 0 ? -1 : 31 - __builtin_clz(t); }
int topbit(ll t) { return t == 0 ? -1 : 63 - __builtin_clzll(t); }
int lowbit(signed a) { return a == 0 ? 32 : __builtin_ctz(a); }
int lowbit(ll a) { return a == 0 ? 64 : __builtin_ctzll(a); }
// int allbit(int n) { return (1 << n) - 1; }
constexpr ll allbit(int n) { return (1LL << n) - 1; }
// int popcount(signed t) { return __builtin_popcount(t); }
// int popcount(ll t) { return __builtin_popcountll(t); }
int popcount(uint64_t t) { return __builtin_popcountll(t); }
bool ispow2(int i) { return i && (i & -i) == i; }

ll rnd(ll l, ll r) { //[l, r)
#ifdef _LOCAL
    static mt19937_64 gen;
#else
    static mt19937_64 gen(chrono::steady_clock::now().time_since_epoch().count());
#endif
    return uniform_int_distribution<ll>(l, r - 1)(gen);
}
ll rnd(ll n) { return rnd(0, n); }

template <class t> void random_shuffle(vc<t> &a) { rep(i, si(a)) swap(a[i], a[rnd(0, i + 1)]); }

int in() {
    int x;
    cin >> x;
    return x;
}
ll lin() {
    unsigned long long x;
    cin >> x;
    return x;
}

template <class T, class S> pair<T, S> operator-(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi - y.fi, x.se - y.se); }
template <class T, class S> pair<T, S> operator+(const pair<T, S> &x, const pair<T, S> &y) { return pair<T, S>(x.fi + y.fi, x.se + y.se); }
template <class T> pair<T, T> operator&(const pair<T, T> &l, const pair<T, T> &r) { return pair<T, T>(max(l.fi, r.fi), min(l.se, r.se)); }
template <class T, class S> pair<T, S> operator+=(pair<T, S> &l, const pair<T, S> &r) { return l = l + r; }
template <class T, class S> pair<T, S> operator-=(pair<T, S> &l, const pair<T, S> &r) { return l = l - r; }
template <class T> bool intersect(const pair<T, T> &l, const pair<T, T> &r) { return (l.se < r.se ? r.fi < l.se : l.fi < r.se); }

template <class T> ll operator*(const pair<T, T> &x, const pair<T, T> &y) { return (ll)x.fi * y.fi + (ll)x.se * y.se; }

template <typename T> struct edge {
    int from, to;
    T cost;
    int id;
    edge(int to, T cost) : from(-1), to(to), cost(cost) {}
    edge(int from, int to, T cost) : from(from), to(to), cost(cost) {}
    edge(int from, int to, T cost, int id) : from(from), to(to), cost(cost), id(id) {}
    constexpr bool operator<(const edge<T> &rhs) const noexcept { return cost < rhs.cost; }
    edge &operator=(const int &x) {
        to = x;
        return *this;
    }
    operator int() const { return to; }
};
template <typename T> using Edges = vector<edge<T>>;

using Tree = vector<vector<int>>;
using Graph = vector<vector<int>>;
template <class T> using Wgraph = vector<vector<edge<T>>>;
Graph getG(int n, int m = -1, bool directed = false, int margin = 1) {
    Tree res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        cin >> a >> b;
        a -= margin, b -= margin;
        res[a].emplace_back(b);
        if(!directed) res[b].emplace_back(a);
    }
    return res;
}
Graph getTreeFromPar(int n, int margin = 1) {
    Graph res(n);
    for(int i = 1; i < n; i++) {
        int a;
        cin >> a;
        res[a - margin].emplace_back(i);
    }
    return res;
}
template <class T> Wgraph<T> getWg(int n, int m = -1, bool directed = false, int margin = 1) {
    Wgraph<T> res(n);
    if(m == -1) m = n - 1;
    while(m--) {
        int a, b;
        T c;
        cin >> a >> b >> c;
        a -= margin, b -= margin;
        res[a].emplace_back(b, c);
        if(!directed) res[b].emplace_back(a, c);
    }
    return res;
}
void add(Graph &G, int x, int y) { G[x].eb(y), G[y].eb(x); }
template <class S, class T> void add(Wgraph<S> &G, int x, int y, T c) { G[x].eb(y, c), G[y].eb(x, c); }

#define i128 __int128_t
#define ull unsigned long long int
#define TEST                                                                                                                                                   \
    INT(testcases);                                                                                                                                            \
    while(testcases--)
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    for(auto it = begin(v); it != end(v); ++it) {
        if(it == begin(v))
            os << *it;
        else
            os << " " << *it;
    }
    return os;
}
template <class T, class S> ostream &operator<<(ostream &os, const pair<T, S> &p) {
    os << p.first << " " << p.second;
    return os;
}
template <class S, class T> string to_string(pair<S, T> p) { return "(" + to_string(p.first) + "," + to_string(p.second) + ")"; }
string to_string(string s) { return "\"" + s + "\""; }
string to_string(char c) { return string(1, c); }
template <class T> string to_string(vector<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it) + (next(it) == s.end() ? "" : ", ");
    return res + "}";
}
template <class T> string to_string(set<T> s) {
    string res = "{";
    for(auto it = s.begin(); it != s.end(); it++) res += to_string(*it), res += (next(it) == end(s) ? "" : ", ");
    return res + "}";
}

#define endl '\n'

#ifdef _LOCAL
void dump() { cerr << endl; }
template <class Head, class... Tail> void dump(Head head, Tail... tail) {
    cerr << to_string(head) << " ";
    dump(tail...);
}
#undef endl
#define debug(x)                                                                                                                                               \
    cout << #x << ": ";                                                                                                                                        \
    dump(x)
#else
void dump() {}
template <class Head, class... Tail> void dump(Head head, Tail... tail) {}
#define debug(x)
#endif
template <class T> void print(const T &a) { cout << a; }
void OUT() { cout << endl; }
template <class Head, class... Tail> void OUT(const Head &head, const Tail &...tail) {
    print(head);
    if(sizeof...(tail)) cout << ' ';
    OUT(tail...);
}

template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
#define drop(s) cout << #s << endl, exit(0)

template <int N> struct ndFORarray {
    std::array<int, N> v;
    ndFORarray(std::array<int, N> v_) : v(v_) {}
    struct ndFORitr {
        const std::array<int, N> &v;
        std::array<int, N> tmp;
        bool is_end;
        ndFORitr(const std::array<int, N> &v_) : v(v_), tmp(), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = N - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::array<int, N> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

struct ndFORvector {
    std::vector<int> v;
    ndFORvector(std::vector<int> v_) : v(v_) {}
    struct ndFORitr {
        const std::vector<int> &v;
        std::vector<int> tmp;
        bool is_end;
        ndFORitr(const std::vector<int> &v_) : v(v_), tmp(v.size(), 0), is_end(false) {}
        bool operator!=(const ndFORitr &) const { return !is_end; }
        void operator++() {
            int pos = v.size() - 1;
            while(pos != -1) {
                tmp[pos] += 1;
                if(tmp[pos] == v[pos]) {
                    tmp[pos] = 0;
                    pos -= 1;
                } else {
                    break;
                }
            }
            if(pos == -1) { is_end = true; }
        }
        const std::vector<int> &operator*() const { return tmp; }
    };
    ndFORitr begin() const { return ndFORitr(v); }
    ndFORitr end() const { return ndFORitr(v); }
};

auto ndFOR(std::vector<int> v) { return ndFORvector(v); }
template <class... Ts> auto ndFOR(Ts... v) { return ndFORarray<std::tuple_size<std::tuple<Ts...>>::value>({v...}); }
template <class F> struct REC {
    F f;
    REC(F &&f_) : f(std::forward<F>(f_)) {}
    template <class... Args> auto operator()(Args &&...args) const { return f(*this, std::forward<Args>(args)...); }
};

template <class S> vector<pair<S, int>> runLength(const vector<S> &v) {
    vector<pair<S, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}
vector<pair<char, int>> runLength(const string &v) {
    vector<pair<char, int>> res;
    for(auto &e : v) {
        if(res.empty() or res.back().fi != e)
            res.eb(e, 1);
        else
            res.back().se++;
    }
    return res;
}

template <class T = int> struct Imos {
    int n;
    vector<T> a;
    Imos(int _n) : n(_n), a(_n + 1) {}
    void add(int l, int r, T val = 1) {
        if(l >= r) return;
        l = clamp(l, 0, n);
        r = clamp(r, 0, n + 1);
        a[l] += val;
        if(r <= n) a[r] -= val;
    }
    void build() {
        for(int i = 0; i < n; i++) a[i + 1] += a[i];
    }
    const T &operator[](int k) { return a[k]; }
};

template <class T> struct RUI {
    vector<T> a;
    RUI(const vector<T> &v) : a(v.size() + 1) {
        for(int i = 0; i < v.size(); i++) a[i + 1] = a[i] + v[i];
    }
    T get(int l, int r) { return a[r] - a[l]; }
};

template <class T, class F> T bin_search(T ok, T ng, const F &f) {
    while(abs(ok - ng) > 1) {
        T mid = ok + ng >> 1;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
template <class T, class F> T bin_search_double(T ok, T ng, const F &f, int iter = 80) {
    while(iter--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

struct Setup_io {
    Setup_io() {
        ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
        cout << fixed << setprecision(15);
    }
} setup_io;
#pragma endregion

int main() {
    while(1) {
        INT(n, m, r);
        if(!n) exit(0);
        VEC(int, a, n);
        VEC(int, b, m);
        rep(i, n) a[i]--;
        rep(i, m) b[i]--;

        struct S {
            vi v;
            vvc<int> match;
            S(vi a) : v(a) { match = vvc<int>(si(a) + 1, vi(si(a) + 1)); }
            S() = default;
        };

        vector<S> A, B;
        rep(i, n) {
            A.eb(a);
            rotate(begin(a), begin(a) + 1, end(a));
        }
        rep(i, n) {
            B.eb(b);
            rotate(begin(b), begin(b) + 1, end(b));
        }

        vector<pair<int, vi>> R;
        rep(i, r) {
            INT(k);
            VEC(int, x, k);
            rep(i, k) x[i]--;
            INT(y);
            y--;
            R.eb(y, x);
        }

        vv(int, DP, 30, 30);
        auto calc = [&](S &s) {
            auto &dp = s.match;
            int n = si(s.v);
            rep2(d, 1, n) {
                rep(i, n) {
                    int j = i + d;
                    if(j > n) break;
                    if(d == 1) {
                        dp[i][j] = 1 << s.v[i];
                        continue;
                    }
                    for(auto &[y, x] : R) {
                        if(dp[i][j] >> y & 1) continue;
                        int k = si(x);
                        rep(i, d + 1) rep(j, k + 1) DP[i][j] = 0;
                        DP[0][0] = 1;
                        rep(ii, d) rep(jj, k) {
                            if(!DP[ii][jj]) continue;
                            rep2(to, ii + 1, d) {
                                int l = i + ii;
                                int r = i + to;
                                if(dp[l][r] >> x[jj] & 1) DP[to][jj + 1] = true;
                            }
                        }
                        if(DP[d][k]) dp[i][j] |= 1 << y;
                    }
                }
            }
        };
        each(e, A) calc(e);
        each(e, B) calc(e);

        int ma = -1;
        each(a, A) each(b, B) {
            rep(i, n + 1) rep(j, m + 1) DP[i][j] = -inf<int>;
            DP[0][0] = 0;
            auto &x = a.match, &y = b.match;
            rep(i, n) rep(j, m) {
                if(DP[i][j] < 0) continue;
                rep2(ii, i + 1, n) rep2(jj, j + 1, m) {
                    if(x[i][ii] & y[j][jj]) chmax(DP[ii][jj], DP[i][j] + 1);
                }
            }
            chmax(ma, DP[n][m]);
        }
        OUT(ma);
    }
}
accuracy: 0.5
time_ms: 390
memory_kb: 3720
final_rank: 20

code_snippet: //#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
using namespace std;

//#define int long long
typedef long long ll;

typedef unsigned long long ul;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;

#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
typedef long double ld;
typedef pair<ld, ld> LDP;
const ld eps = 1e-8;
const ld pi = acosl(-1.0);

ll mod_pow(ll x, ll n, ll m = mod) {
	if (n < 0) {
		ll res = mod_pow(x, -n, m);
		return mod_pow(res, m - 2, m);
	}
	if (abs(x) >= m)x %= m;
	if (x < 0)x += m;
	ll res = 1;
	while (n) {
		if (n & 1)res = res * x % m;
		x = x * x % m; n >>= 1;
	}
	return res;
}
struct modint {
	ll n;
	modint() :n(0) { ; }
	modint(ll m) :n(m) {
		if (n >= mod)n %= mod;
		else if (n < 0)n = (n % mod + mod) % mod;
	}
	operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
	if (n == 0)return modint(1);
	modint res = (a * a) ^ (n / 2);
	if (n % 2)res = res * a;
	return res;
}

ll inv(ll a, ll p) {
	return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
	fact[0] = modint(1);
	for (int i = 0; i < max_n - 1; i++) {
		fact[i + 1] = fact[i] * modint(i + 1);
	}
	factinv[max_n - 1] = modint(1) / fact[max_n - 1];
	for (int i = max_n - 2; i >= 0; i--) {
		factinv[i] = factinv[i + 1] * modint(i + 1);
	}
}
modint comb(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
	if (a < 0 || b < 0 || a < b)return 0;
	return fact[a] * factinv[a - b];
}
int gcd(int a, int b) {
	if (a < b)swap(a, b);
	while (b) {
		int r = a % b; a = b; b = r;
	}
	return a;
}

const int c = 31;
bool ok[55][55][c];
bool sub[55][11];
vector<vector<int>> mk[c];
void yaru(vector<int> a) {
	int n = a.size();
	rep(i, n)Rep(j, i+1, n+1)rep(k, c)ok[i][j][k] = false;
	rep(i, n)ok[i][i+1][a[i]] = true;
	for (int len = 2; len <= n; len++) {
		rep(l, n - len + 1) {
			int r = l + len;
			//[l,r)
			rep(col, c) {
				for (auto v : mk[col]) {
					Rep1(i, l, r)rep(j, v.size()+1) {
						sub[i][j] = false;
					}
					sub[l][0] = true;
					Rep(i, l, r) {
						rep(j, v.size())if (sub[i][j]) {
							for (int ni = i + 1; ni <= r; ni++) {
								if (ok[i][ni][v[j]]) {
									sub[ni][j + 1] = true;
								}
							}
						}
					}
					if (sub[r][v.size()]) {
						ok[l][r][col] = true; break;
					}
				}
			}
		}
	}
}

bool oka[55][55][c];
bool okb[55][55][c];
int n, m, r;

bool sok[55][55][55][55];
void solve() {
	rep(i, c)mk[i].clear();
	vector<int> a(n);
	rep(i, n)cin >> a[i]; rep(i, n)a.push_back(a[i]);
	vector<int> b(m);
	rep(i, m)cin >> b[i]; rep(i, m)b.push_back(b[i]);
	rep(i, r) {
		int num; cin >> num;
		vector<int> v(num);
		rep(j, num)cin >> v[j];
		int alf; cin >> alf;
		mk[alf].push_back(v);
	}
	yaru(a);
	rep(i, a.size())Rep1(j, i + 1, a.size())rep(k, c) {
		oka[i][j][k] = ok[i][j][k];
	}
	yaru(b);
	rep(i, b.size())Rep1(j, i + 1, b.size())rep(k, c) {
		okb[i][j][k] = ok[i][j][k];
	}
	rep(i, a.size())Rep(j, i + 1, a.size() + 1) {
		rep(k, b.size())Rep(l, k + 1, b.size() + 1) {
			sok[i][j][k][l] = false;
			rep(col, c) {
				if (oka[i][j][col] && okb[k][l][col]) {
					sok[i][j][k][l] = true; break;
				}
			}
		}
	}
	int ans = -1;
	rep(s, n)rep(t, m) {
		//[s,s+n)
		//[t,t+m)
		vector<vector<int>> dp(n + 1, vector<int>(m + 1,-1));
		dp[0][0] = 0;
		rep(i, n + 1)rep(j, m + 1) {
			if (dp[i][j] < 0)continue;
			for (int ni = i + 1; ni <= n; ni++) {
				for (int nj = j + 1; nj <= m; nj++) {
					if (sok[s + i][s + ni][t + j][t + nj]) {
						dp[ni][nj] = max(dp[ni][nj], dp[i][j] + 1);
					}
				}
			}
		}
		ans = max(ans, dp[n][m]);
	}
	cout << ans << "\n";
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(10);
	//init_f();
	//init();
	//int t; cin >> t; rep(i, t)
	while (cin>>n>>m>>r,n)
		solve();
	return 0;
}
accuracy: 1
time_ms: 510
memory_kb: 28656
final_rank: 16

code_snippet: /*	author:  Kite_kuma
	created: 2021.08.25 09:49:47 */

// #ifdef LOCAL
#define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

vvvi make_dp_table(vector<int> a, vector<vi> x, vector<int> y) {
	int n = a.size();
	int n2 = n + n;
	int r = x.size();
	rep(i, n) a.push_back(a[i]);
	VV<VV<int>> dp_rule(n, vvvi(n2, vvi(r, vi(11))));

	vvvi ret(n, vvi(n2, vi(31)));

	rep(len, 0, n + 1) {
		rep(left, n) {
			int right = left + len;
			rep(rule_number, r) {
				rep(xr, 0, x[rule_number].size() + 1) {
					// dp_rule[left][right][rulenumber][xr]
					auto &change = dp_rule[left][right][rule_number][xr];

					if(len == 0) {
						change = (xr == 0);
					} else {
						if(!xr) continue;
						if(len == 1) {
							if(a[left] == x[rule_number][0] && xr == 1) {
								change = 1;
							}
						} else {
							rep(mid, left + 1, right) {
								int m = mid;
								int R = right;
								if(m >= n) {
									m -= n;
									R -= n;
								}
								change |= (dp_rule[left][mid][rule_number][xr - 1] && ret[m][R][x[rule_number][xr - 1]]);
							}
						}
					}
				}
			}

			auto &change = ret[left][right];
			if(len == 1) {
				change[a[left]] = 1;
				continue;
			}

			rep(rule_number, r) {
				if(dp_rule[left][right][rule_number][x[rule_number].size()]) {
					change[y[rule_number]] = 1;
				}
			}

			rep(rule_number, r){
				rep(number, 31){
					if(x[rule_number][0] == number && change[number]){
						dp_rule[left][right][rule_number][1] = 1;
					}
				}
			}
		}
	}

	return ret;
}

int solve(int n) {
	int m, r;
	cin >> m >> r;

	vector<int> a, b;
	rep(n) {
		INT(x);
		a.push_back(x);
	}
	rep(m) {
		INT(x);
		b.push_back(x);
	}

	// vector<pair<vector<int>, int>> rules;
	vvi x(r);
	vi y(r);
	rep(i, r) {
		int len;
		cin >> len;
		x[i].resize(len);
		rep(j, len) cin >> x[i][j];
		cin >> y[i];
	}

	debug(x, y);

	auto dp_a = make_dp_table(a, x, y);
	auto dp_b = make_dp_table(b, x, y);


	rep(i, n) a.push_back(a[i]);
	rep(i, m) b.push_back(b[i]);

	int n2 = n + n;
	int m2 = m + m;

	vvi longest_path(n2, vi(m2));

	VV<VV<int>> match(n, vvvi(n2, vvi(m, vi(m2))));

	rep(i, n) rep(j, i + 1, n2) rep(k, m) rep(l, k + 1, m2) {
		rep(num, 31) {
			if(dp_a[i][j][num] && dp_b[k][l][num]) {
				match[i][j][k][l] = 1;
			}
		}
	}

	int ans = -1;

	rep(start_a, n) rep(start_b, m) {
		int goal_a = start_a + n;
		int goal_b = start_b + m;

		vvi dp(n + 1, vi(m + 1, -inf));
		dp[0][0] = 0;

		rep(i, start_a + 1, goal_a + 1) rep(j, start_b + 1, goal_b + 1) {
			rep(pre_i, start_a, i) rep(pre_j, start_b, j) {
				int c, d, e, f;
				if(pre_i >= n) {
					c = pre_i - n;
					d = i - n;
				} else {
					c = pre_i;
					d = i;
				}
				if(pre_j >= m) {
					e = pre_j - m;
					f = j - m;
				} else {
					e = pre_j;
					f = j;
				}
				if(match[c][d][e][f]) {
					chmax(dp[i - start_a][j - start_b], dp[pre_i - start_a][pre_j - start_b] + 1);
				}
			}
		}

		chmax(ans, dp[n][m]);
	}

	return ans;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n) {
		if(!n) exit(0);
		cout << solve(n) << dl;
	}

	return 0;
}
accuracy: 1
time_ms: 2860
memory_kb: 12612
final_rank: 15

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<typename T>
std::vector<T> table(int n, T v) { return std::vector<T>(n, v); }

template <class... Args>
auto table(int n, Args... args) {
    auto val = table(args...);
    return std::vector<decltype(val)>(n, std::move(val));
}

constexpr int max_a = 30;
constexpr int max_k = 10;

auto calc_can_make(vector<int> const& a, vector<vector<int>> const& xs, vector<int> const& ys) {
    const int n = a.size() / 2, r_sz = xs.size();
    auto can_make = table(a.size(), a.size(), max_a + 1, false);
    // r_dp[i][j][k][l] := can match a[i..j) with xs[k][0..l) ?
    auto r_dp = table(a.size(), a.size(), r_sz, max_k + 1, false);
    for(int i = 0; i + 1 < n * 2; ++i) {
        can_make[i][i + 1][a[i]] = true;
    }
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < r_sz; ++j) {
            r_dp[i][i][j][0] = true;
        }
    }
    for(int len = 1; len <= n; ++len) {
        for(int l = 0; l + len < 2 * n; ++l) {
            const int r = l + len;
            for(int i = 0; i < r_sz; ++i) {
                for(int j = 1; j <= (int)xs[i].size(); ++j) {
                    for(int k = l; k < r; ++k) {
                        r_dp[l][r][i][j] = r_dp[l][r][i][j] | (r_dp[l][k][i][j - 1] && can_make[k][r][xs[i][j - 1]]);
                    }
                }
            }
            for(int i = 0; i < r_sz; ++i) {
                if(r_dp[l][r][i][xs[i].size()]) {
                    can_make[l][r][ys[i]] = true;
                }
            }
            for(int i = 0; i < r_sz; ++i) {
                if(can_make[l][r][xs[i][0]]) {
                    r_dp[l][r][i][1] = true;
                }
            }
        }
    }
    return can_make;
}

int main() {
    int n, m, r;
    while(cin >> n >> m >> r, n) {
        vector<int> a(n * 2), b(m * 2);
        vector<vector<int>> xs(r);
        vector<int> ys(r);
        for(int i = 0; i < n; ++i) {
            cin >> a[i];
            a[i + n] = a[i];
        }
        for(int i = 0; i < m; ++i) {
            cin >> b[i];
            b[i + m] = b[i];
        }
        for(int i = 0; i < r; ++i) {
            int k; cin >> k;
            xs[i].resize(k);
            for(auto& x : xs[i]) cin >> x;
            cin >> ys[i];
        }

        auto can_make_a = calc_can_make(a, xs, ys);
        auto can_make_b = calc_can_make(b, xs, ys);
        int ans = -1;
        for(int s1 = 0; s1 < n; ++s1) {
            for(int s2 = 0; s2 < m; ++s2) {
                vector<vector<int>> dp(n + 1, vector<int>(m + 1, -1));
                dp[0][0] = 0;
                for(int i = 0; i < n; ++i) {
                    for(int j = 0; j < m; ++j) {
                        if(dp[i][j] == -1) continue;
                        for(int k = 1; k <= 30; ++k) {
                            for(int l1 = 1; l1 <= n - i; ++l1) {
                                if(!can_make_a[s1 + i][s1 + i + l1][k]) continue;
                                for(int l2 = 1; l2 <= m - j; ++l2) {
                                    if(can_make_a[s1 + i][s1 + i + l1][k] && can_make_b[s2 + j][s2 + j + l2][k]) {
                                        dp[i + l1][j + l2] = max(dp[i + l1][j + l2], dp[i][j] + 1);
                                    }
                                }
                            }
                        }
                    }
                }
                ans = max(ans, dp[n][m]);
            }
        }

        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 1920
memory_kb: 14220
final_rank: 14

code_snippet: #include <bits/stdc++.h>

class Solve {
private:
	using vi = std::vector<int>;
	using vvi = std::vector<vi>;
	using vvvi = std::vector<vvi>;
	using vvvvi = std::vector<vvvi>;

	using vb = std::vector<bool>;
	using vvb = std::vector<vb>;
	using vvvb = std::vector<vvb>;

	int n, m, r;
	vvvi R;

	vi inputVector(int size)
	{
		std::vector<int> ret(size);
		for (auto& e: ret)
		{
			scanf("%d", &e);
			e--;
		}
		return std::move(ret);
	}
	void inputR()
	{
		R.resize(30);
		for (int i{}; i < r; i++)
		{
			int k;
			scanf("%d", &k);
			std::vector<int> tmp(k);
			for (auto& e: tmp)
			{
				scanf("%d", &e);
				e--;
			}
			int y;
			scanf("%d", &y);
			y--;
			R[y].push_back(tmp);
		}
	}

	void execute(vi& arr, vvvi& charTable, vvvb& canMake)
	{
		int size{(int)arr.size()};
		for (int i{}; i < size; i++)
		{
			charTable[i][arr[i]].push_back((i + 1) % size);
			canMake[i][(i + 1) % size][arr[i]] = true;
		}
		for (int width{2}; width <= size; width++)
			for (int left{}; left < size; left++)
				for (int char_i{}; char_i < 30; char_i++)
					for (auto& e: R[char_i])
						if (e.size() <= width && stringFound(e, 0, left, width, charTable, canMake))
						{
							charTable[left][char_i].push_back((left + width) % size);
							canMake[left][(left + width) % size][char_i] = true;
							break;
						}
	}

	bool stringFound(vi& arr, int arr_i, int left, int width, vvvi& charTable, vvvb& canMake)
	{
		int char_i{arr[arr_i]}, size{(int)charTable.size()};
		if (arr_i + 1 == (int)arr.size())
			return canMake[left][(left + width) % size][char_i];
		for (auto& e: charTable[left][char_i])
		{
			int next_width{e};
			if (e <= left) next_width += size;
			next_width -= left;
			if ((int)arr.size() - (arr_i + 1) > width - next_width) break;
			if (stringFound(arr, arr_i + 1, e, width - next_width, charTable, canMake))
				return true;
		}
		return false;
	}

public:
	bool is_last_query{};
	Solve()
	{
		scanf("%d%d%d", &n, &m, &r);
		if (n == 0)
		{
			is_last_query = true;
			return;
		}
		vi A(inputVector(n)), B(inputVector(m));
		inputR();
		vvvb canMakeA(n, vvb(n, vb(30))), canMakeB(m, vvb(m, vb(30)));
		vvvi charTableA(n, vvi(30)), charTableB(m, vvi(30));
		execute(A, charTableA, canMakeA);
		execute(B, charTableB, canMakeB);
		vvvvi dp(n, vvvi(n, vvi(m, vi(m))));
		for (int la{}; la < n; la++)
			for (int lb{}; lb < m; lb++)
				for (int ra{}; ra < n; ra++)
					for (int rb{}; rb < m; rb++)
						for (int char_i{}; char_i < 30; char_i++)
							if (canMakeA[la][ra][char_i] && canMakeB[lb][rb][char_i])
								dp[la][ra][lb][rb] = 1;
		for (int wa{2}; wa <= n; wa++)
			for (int wb{2}; wb <= m; wb++)
				for (int la{}; la < n; la++)
				{
					int ra{(la + wa) % n};
					for (int lb{}; lb < m; lb++)
					{
						int rb{(lb + wb) % m};
						for (int ma{(la + 1) % n}; ma != ra; ma = (ma + 1) % n)
							for (int mb{(lb + 1) % m}; mb != rb; mb = (mb + 1) % m)
								if (dp[la][ma][lb][mb] > 0 && dp[ma][ra][mb][rb] > 0)
									dp[la][ra][lb][rb] = std::max(dp[la][ra][lb][rb], dp[la][ma][lb][mb] + dp[ma][ra][mb][rb]);
					}
				}
		int max{};

		for (int la{}; la < n; la++)
			for (int lb{}; lb < m; lb++)
				max = std::max(max, dp[la][la][lb][lb]);
		if (max == 0) puts("-1");
		else printf("%d\n", max);
	}
};

int main()
{
	while (!Solve().is_last_query);

	return 0;
}
accuracy: 1
time_ms: 2660
memory_kb: 5452
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define NUM 60

enum Type{
	A,
	B,
};

int len[2],num_rule;
int table[2][NUM];
int num_left[NUM],from_table[NUM][10],to_table[NUM];
int max_match[NUM][NUM];
bool dp[2][NUM][NUM][30];
bool dp2[2][NUM][NUM][NUM][11];

void make_dp(Type type){

	int calc_len = 2*len[type]-1;

	for(int left = 0; left < calc_len; left++){
		for(int right = left; right < calc_len; right++){

			for(int num = 0; num < 30; num++){
				dp[type][left][right][num] = false;
			}

			for(int i = 0; i < num_rule; i++){
				for(int k = 0; k <= num_left[i]; k++){
					dp2[type][left][right][i][k] = false;
				}
			}
		}
	}

	for(int i = 0; i < calc_len; i++){
		dp[type][i][i][table[type][i]] = true;
	}

	int right;

	for(int length = 1; length <= len[type]; length++){
		for(int left = 0; left+length <= calc_len; left++){

			right = left+length-1;

			for(int i = 0; i < num_rule; i++){
				for(int k = 0; k < num_left[i]; k++){
					for(int mid = left; mid < right; mid++){

						if(dp2[type][left][mid][i][k] == true && dp[type][mid+1][right][from_table[i][k]] == true){
							dp2[type][left][right][i][k+1] = true;
						}
					}
				}
			}

			for(int i = 0; i < num_rule; i++){
				if(dp2[type][left][right][i][num_left[i]]){
					dp[type][left][right][to_table[i]] = true;
				}
			}

			for(int i = 0; i < num_rule; i++){
				if(dp[type][left][right][from_table[i][0]]){
					dp2[type][left][right][i][1] = true;
				}
			}
		}
	}
}

void func(){

	for(int i = 0; i < len[A]; i++){

		scanf("%d",&table[A][i]);
		table[A][i]--;
		table[A][i+len[A]] = table[A][i];
	}

	for(int i = 0; i < len[B]; i++){

		scanf("%d",&table[B][i]);
		table[B][i]--;
		table[B][i+len[B]] = table[B][i];
	}

	for(int i = 0; i < num_rule; i++){

		scanf("%d",&num_left[i]);

		for(int k = 0; k < num_left[i]; k++){
			scanf("%d",&from_table[i][k]);
			from_table[i][k]--;
		}
		scanf("%d",&to_table[i]);
		to_table[i]--;
	}

	make_dp(A);
	make_dp(B);

	int ans = -1;
	int A_right,B_right;

	for(int A_left = 0; A_left < len[A]; A_left++){
		for(int B_left = 0; B_left < len[B]; B_left++){

			for(int i = 0; i <= len[A]; i++){
				for(int k = 0; k <= len[B]; k++){
					max_match[i][k] = -1;
				}
			}

			max_match[0][0] = 0;

			for(int len_A = 1; len_A <= len[A]; len_A++){
				A_right = A_left+len_A-1;
				for(int len_B = 1; len_B <= len[B]; len_B++){
					B_right = B_left+len_B-1;
					for(int A_mid = A_left; A_mid <= A_right; A_mid++){
						for(int B_mid = B_left; B_mid <= B_right; B_mid++){
							if(max_match[A_mid-A_left][B_mid-B_left] == -1)continue;

							for(int i = 0; i < 30; i++){
								if(dp[A][A_mid][A_right][i] == true && dp[B][B_mid][B_right][i] == true){
									max_match[len_A][len_B] = max(max_match[len_A][len_B],max_match[A_mid-A_left][B_mid-B_left]+1);
								}
							}
						}
					}
				}
				ans = max(ans,max_match[len[A]][len[B]]);
			}
		}
	}
	printf("%d\n",ans);
}

int main(){

	while(true){
		scanf("%d %d %d",&len[A],&len[B],&num_rule);
		if(len[A] == 0 && len[B] == 0 && num_rule == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 7170
memory_kb: 5380
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

int main(){
    int n,m,RULE;
    while(scanf(" %d %d %d", &n, &m, &RULE),n){
        vector<int> A(n),B(m);
        rep(i,n){
            scanf(" %d", &A[i]);
            --A[i];
        }
        rep(i,m){
            scanf(" %d", &B[i]);
            --B[i];
        }

        vector< pair<vector<int>,int> > rule(RULE);
        rep(i,RULE){
            int k;
            scanf(" %d", &k);

            vector<int> x(k);
            int y;
            rep(j,k){
                scanf(" %d", &x[j]);
                --x[j];
            }
            scanf(" %d", &y);
            --y;

            rule[i] = {x,y};
        }

        auto make_f = [&](vector<int> &v){
            int V = v.size();
            int N = 2*V;
            vector<vector<int>> f(N,vector<int>(N));

            rep(i,N){
                int vv = v[i%V];
                f[i][i] |= (1<<vv);
            }

            for(int b=2; b<=V; ++b){
                for(int l=0; l+b-1<N; ++l){
                    int r = l+b-1;

                    // calc f[l][r]
                    rep(rr,RULE){
                        vector<int> x = rule[rr].fi;
                        int y = rule[rr].se;

                        int X = x.size();
                        vector<vector<bool>> valid(b+1, vector<bool>(X+1));
                        valid[0][0] = true;
                        rep(i,b)rep(j,X)if(valid[i][j]){
                            int val = x[j];
                            for(int k=i; k<b; ++k){
                                if(f[l+i][l+k]>>val&1) valid[k+1][j+1] = true;
                            }
                        }

                        if(valid[b][X]) f[l][r] |= (1<<y);
                    }
                }
            }

            // rep(i,N)rep(j,N) printf("f[%d][%d] = %d\n",i,j,f[i][j]);
            return f;
        };

        vector<vector<int>> fa = make_f(A), fb = make_f(B);
        int ans = -1;
        rep(i,n)rep(j,m){
            // printf("CALC %d %d\n",i,j);
            vector<vector<int>> dp(n+1,vector<int>(m+1,-1));
            dp[0][0]=0;
            rep(ii,n)rep(jj,m)if(dp[ii][jj]>=0){
                for(int ni=ii+1; ni<=n; ++ni)for(int nj=jj+1; nj<=m; ++nj){
                    if(fa[i+ii][i+ni-1]&fb[j+jj][j+nj-1]) dp[ni][nj] = max(dp[ni][nj], dp[ii][jj]+1);
                }
            }
            ans = max(ans, dp[n][m]);
        }

        printf("%d\n", ans);
    }
    return 0;
}
accuracy: 1
time_ms: 1030
memory_kb: 3288
final_rank: 4