Language: C++

#include <cstdio>
#include <cstring>
#include <deque>
#include <vector>
#include <algorithm>
//#include <windows.h>

using namespace std;

char dp[50][51][50][51], dp2[2][50][51][60][10], dp3[2][50][51][31];
short visited1[50][51][50][51], visited2[2][50][51][60][10], visited3[2][50][51][31];
vector <int> trans[60];
vector <int> transHash[31];
vector <int> reqLength[2][50][31];

deque <int> inp[2];
int n, m, r;

int caseN;

int transPossible(int, int, int, int, int);

int canConvergeTo(int type, int s, int e, int tarnum)
{
	if(s >= e) return 0;
	int &ret = dp3[type][s][e][tarnum];
	if(visited3[type][s][e][tarnum]) return ret;
	
	ret = 0;
	for(int i = 0; i < transHash[tarnum].size(); i++)
	{
		int ntind = transHash[tarnum][i];
		if(transPossible(type, s, e, ntind, 0)) return ret = 1;
	}

	return ret;
}

int transPossible(int type, int s, int e, int ttype, int tind)
{
	if(trans[ttype].size() == tind)
	{
		if(s == e) return 1;
		return 0;
	}
	if(s >= e) return 0;
	if(e - s < (int)trans[ttype].size() - tind) return 0;

	int &ret = dp2[type][s][e][ttype][tind];
	if(visited2[type][s][e][ttype][tind] == caseN) return ret;
	visited2[type][s][e][ttype][tind] = caseN;

	ret = 0;
	if(inp[type][s] == trans[ttype][tind] && transPossible(type, s + 1, e, ttype, tind + 1)) return ret = 1;
	int tar = trans[ttype][tind], shouldLeft = (int)trans[ttype].size() - tind - 1;
	for(int i = s + 1; i <= e - shouldLeft; i++)
		if(canConvergeTo(type, s, i, tar) && transPossible(type, i, e, ttype, tind + 1)) return ret = 1;
	
	return ret;
}

int getAns(int s1, int e1, int s2, int e2)
{
	if(s1 == e1 && s2 == e2) return 0;
	if(s1 >= e1 || s2 >= e2) return -2;
	
	int &ret = dp[s1][e1][s2][e2];
	if(visited1[s1][e1][s2][e2] == caseN) return ret;
	visited1[s1][e1][s2][e2] = caseN;

	ret = -2;
	int v1 = inp[0][s1], v2 = inp[1][s2];
	int res;

	if(v1 == v2 && (res = getAns(s1 + 1, e1, s2 + 1, e2)) != -2) ret = max(ret, res + 1);

	for(int i = 0; i < reqLength[1][s2][v1].size(); i++)
	{
		int req = reqLength[1][s2][v1][i];
		if((res = getAns(s1 + 1, e1, s2 + req, e2)) != -2) ret = max(ret, res + 1);
	}

	for(int i = 0; i < reqLength[0][s1][v2].size(); i++)
	{
		int req = reqLength[0][s1][v2][i];
		if((res = getAns(s1 + req, e1, s2 + 1, e2)) != -2) ret = max(ret, res + 1);
	}	

	for(int tv = 0; tv <= 30; tv++)
	{
		for(int i = 0; i < reqLength[0][s1][tv].size() && s1 + reqLength[0][s1][tv][i] <= e1; i++)
			for(int j = 0; j < reqLength[1][s2][tv].size() && s2 + reqLength[1][s2][tv][j] <= e2; j++)
			{
				int req1 = reqLength[0][s1][tv][i];
				int req2 = reqLength[1][s2][tv][j];
				if((res = getAns(s1 + req1, e1, s2 + req2, e2)) != -2) ret = max(ret, res + 1);
			}
	}
	return ret;
}

int main(void)
{
	while(scanf("%d %d %d", &n, &m, &r), n)
	{
		caseN++;

		inp[0].resize(n), inp[1].resize(m);
		for(int i = 0; i < n; i++) scanf("%d", &inp[0][i]);
		for(int i = 0; i < m; i++) scanf("%d", &inp[1][i]);
		for(int i = 0; i < n; i++) inp[0].push_back(inp[0][i]);
		for(int i = 0; i < m; i++) inp[1].push_back(inp[1][i]);


		for(int i = 0; i <= 30; i++) transHash[i].clear();
		for(int i = 0; i < r; i++)
		{
			int K;
			scanf("%d", &K);
			trans[i].resize(K);
			for(int j = 0; j < K; j++) scanf("%d", &trans[i][j]);
			int to;
			scanf("%d", &to);
			transHash[to].push_back(i);
		}

		int ans = -1;

//		int curTime = GetTickCount();

		for(int i = 0; i < 50; i++) for(int j = 0; j <= 30; j++) reqLength[0][i][j].clear(), reqLength[1][i][j].clear();

		for(int i = 0; i < n * 2; i++)
			for(int j = i + 2; j <= n * 2; j++)
				for(int k = 0; k <= 30; k++)
				{
					vector <int> &tar = reqLength[0][i][k];
					for(int q = 0; q < transHash[k].size(); q++)
					{
						int ti = transHash[k][q];
						if(transPossible(0, i, j, ti, 0)) tar.push_back(j - i);
					}
					sort(tar.begin(), tar.end());
					tar.erase(unique(tar.begin(), tar.end()), tar.end());
				}

		for(int i = 0; i < m * 2; i++)
			for(int j = i + 2; j <= m * 2; j++)
				for(int k = 0; k <= 30; k++)
				{
					vector <int> &tar = reqLength[1][i][k];
					for(int q = 0; q < transHash[k].size(); q++)
					{
						int ti = transHash[k][q];
						if(transPossible(1, i, j, ti, 0)) reqLength[1][i][k].push_back(j - i);
					}
					sort(tar.begin(), tar.end());
					tar.erase(unique(tar.begin(), tar.end()), tar.end());
				}

//		fprintf(stderr, "%d, ", GetTickCount() - curTime);
//		curTime = GetTickCount();

		for(int i = 0; i < n; i++)
			for(int j = 0; j < m; j++)
				ans = max(ans, getAns(i, i + n, j, j + m));

//		fprintf(stderr, "%d\n", GetTickCount() - curTime);

		printf("%d\n", ans);
	}

	return 0;
}

Compiler output:
a.cc: In function 'int canConvergeTo(int, int, int, int)':
a.cc:26:42: error: cannot bind non-const lvalue reference of type 'int&' to a value of type 'char'
   26 |         int &ret = dp3[type][s][e][tarnum];
      |                    ~~~~~~~~~~~~~~~~~~~~~~^
a.cc: In function 'int transPossible(int, int, int, int, int)':
a.cc:49:47: error: cannot bind non-const lvalue reference of type 'int&' to a value of type 'char'
   49 |         int &ret = dp2[type][s][e][ttype][tind];
      |                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~^
a.cc: In function 'int getAns(int, int, int, int)':
a.cc:67:37: error: cannot bind non-const lvalue reference of type 'int&' to a value of type 'char'
   67 |         int &ret = dp[s1][e1][s2][e2];
      |                    ~~~~~~~~~~~~~~~~~^