#include <stdio.h>
//#include <string.h> //////////////////////////////////////////////////////////////////////////////
//#include <conio.h>/////////////////////////////////////////////////////////////////////////////////

int N,M;
int dojrzaly[1002]; // 1 k
int pi[1002];
int podzialy[501][1001]; // 0.5 kk
int minimalna_liczba_pokolen=1000000;
int SZUKANY[1002];
int Znaleziony[70002][503]; // 35 kk
int lista_kolejnych_krokow[5000001][2]; // 5 kk
int wskaz_lista=0;
//FILE *plik;
int Byla_PARA[501][501]; // 0.25 kk
int Byl_JEDEN[501];


int Poprzednie_Pokolenie(int pokolenie, int pasujace)
{

//printf("pokolenie=%ld, pasujace=%ld, wskaz_lista=%ld\nSZUKANY: [",pokolenie,pasujace,wskaz_lista);
//for (int e=1;e<=SZUKANY[0]; e++) printf("%ld ",SZUKANY[e]);
//printf("]\n\n");
//if (pokolenie%1000==0) getch();
//getch();

// Dwa różne przypadki:
// - jeśli zaczynam przy zerowym "pasujacym"
// - jeśli już mam jakieś pasujące
//if (pasujace==0)
if ((pasujace==0) && (pokolenie<minimalna_liczba_pokolen))
	{
	//Stworzenie nowej tablicy pi? ... Musiałaby być w sumie lokalna dla każdego przypadku...
	//Ale nie mogę też tworzyć tyle instancji tych tablic, bo się w pamięci nie zmieszczę... 
	//Stworzona raz i na niej przejrzane wszystkie komórki - dzięki temu stworzona lista kolejnych kroków i wg tej listy pogłębianie.
	//Będę zapamiętywać dwie liczby - początkowy i końcowy index w tablicy globalnej, w której będę zapisywać wszystkie, które mogłyby się przydać.
	int wskaz_pocz=wskaz_lista+1;
	int wskaz_kon,k;
	pi[1]=0;
	k=0;
	for (int i=2; i<=SZUKANY[0]; i++)
		{
		while ((k>0) && ( SZUKANY[k+1] != SZUKANY[i] )) k=pi[k];
		if (SZUKANY[k+1] == SZUKANY[i]) k++;
		pi[i]=k;
		}
	
	// Wyszukiwanie przy użyciu tablicy pi spośród wszystkich komórek:
	for (int komorka=1; komorka<=N; komorka++)
		{
		int k=0; // Liczba prawidłowych wartości
		for (int i=1; i<=podzialy[komorka][0]; i++)
			{
			while ((k>0) && (SZUKANY[k+1] != podzialy[komorka][i])) k=pi[k];
			if (SZUKANY[k+1] == podzialy[komorka][i]) k++;
			if (k==SZUKANY[0])
				{
				// Cały SZUKANY został znaleziony
				wskaz_lista++;
				lista_kolejnych_krokow[wskaz_lista][0]=komorka;
				lista_kolejnych_krokow[wskaz_lista][1]=-k;
				//Caly_Znaleziony=1;
				break;
				// k=pi[k];
				// Nie muszę kontynuować - lepiej, żeby znalazł całość w środku, niż tylko fragment
				}
			if (i==podzialy[komorka][0])
				{
				// Końcówka podziału pasuje do SZUKANEGO
				while (k!=0)
					{
					wskaz_lista++;
					lista_kolejnych_krokow[wskaz_lista][0]=komorka;
					lista_kolejnych_krokow[wskaz_lista][1]=k;
					k=pi[k];
					}
				}
			}
		} //for komorka=1:N
	
	wskaz_kon=wskaz_lista;
	
	for (int i=wskaz_pocz; i<=wskaz_kon; i++)
		{
		if (lista_kolejnych_krokow[i][1]<0)
			{
			// Zatem znaleziono całość jako jeden wyraz
			//należy przejść jedno pokolenie głębiej, podmienić SZUKANY na Znaleziony i kontynuować 
			//	(po powrocie z rekurencji trzeba przywrócić wartość, więc pewnie także jakaś wewnętrzna pamięć będzie konieczna...)
			
			Znaleziony[pokolenie][0]++;
			Znaleziony[pokolenie][ Znaleziony[pokolenie][0] ] = lista_kolejnych_krokow[i][0];
			
			// I jeszcze się upewnić, że chwilę wcześniej nie było identycznego...
			if (lista_kolejnych_krokow[i][0] == 1)
				{
				// Czyli udało się dotrzeć do pierwszego pokolenia.
				if (pokolenie < minimalna_liczba_pokolen) 
					{
					minimalna_liczba_pokolen=pokolenie;
					}
				
				
				/*printf("ZNALEZIONO dla liczby pokolen=%ld\n",pokolenie);
				for (int pok=pokolenie; pok>=2; pok--)
					{
					printf("Znaleziony[%ld]: ",pok);
					for (int jj=1; jj<=Znaleziony[pok][0]; jj++) printf("%ld ",Znaleziony[pok][jj]);
					printf("\n");
					}
				printf("\n");
				*/
				}
			else
				{ // Mamy już jednowyrazowy, ale jeszcze nie ten pierwotny (1)
				int juz_bylo=0;
				if (Znaleziony[pokolenie][0] < 3) //
					{
					
					if ((Znaleziony[pokolenie][0] == 2) && (Byla_PARA[ Znaleziony[pokolenie][1] ][ Znaleziony[pokolenie][2] ] == 1)) juz_bylo=1;
					if ((Znaleziony[pokolenie][0] == 1) && (Byl_JEDEN[ Znaleziony[pokolenie][1] ] == 1)) juz_bylo=1;
					
					/*
					int bb=pokolenie;
					while (Znaleziony[bb-1][0]==Znaleziony[pokolenie][0])
						{
						if ((Znaleziony[bb-1][0]==2) && (Znaleziony[bb-1][1]==Znaleziony[pokolenie][1]) && (Znaleziony[bb-1][2]==Znaleziony[pokolenie][2])) { juz_bylo=1; break; }
						if ((Znaleziony[bb-1][0]==1) && (Znaleziony[bb-1][1]==Znaleziony[pokolenie][1])) { juz_bylo=1; break; }
						bb--;
						}
					*/
					
					}
				if (juz_bylo==0)
					{
					// Tutaj mam pewność, że mogę iść dalej, bo wcześniej się nie powtórzyło
					int *w_SZUK;
					w_SZUK = new int[SZUKANY[0]+1];
					for (int yy=0; yy<=SZUKANY[0]; yy++) w_SZUK[yy]=SZUKANY[yy];
					
					if (Znaleziony[pokolenie][0]==2) Byla_PARA[ Znaleziony[pokolenie][1] ][ Znaleziony[pokolenie][2] ] = 1;
					else if (Znaleziony[pokolenie][0]==1) Byl_JEDEN[ Znaleziony[pokolenie][1] ] = 1;
					
					
					for (int yy=0; yy<=Znaleziony[pokolenie][0]; yy++) SZUKANY[yy]=Znaleziony[pokolenie][yy];
					Poprzednie_Pokolenie(pokolenie+1, 0);
					
					
					if (Znaleziony[pokolenie][0]==2) Byla_PARA[ Znaleziony[pokolenie][1] ][ Znaleziony[pokolenie][2] ] = 0;
					else if (Znaleziony[pokolenie][0]==1) Byl_JEDEN[ Znaleziony[pokolenie][1] ] = 0;
					
					for (int yy=0; yy<=w_SZUK[0]; yy++) SZUKANY[yy]=w_SZUK[yy];
					delete [] w_SZUK;
					}
				
				}
			
			Znaleziony[pokolenie][0]--;
			}
		else //Czyli po prostu znaleziono fragment (początek SZUKANEGO)
			{
			Znaleziony[pokolenie][0]++;
			Znaleziony[pokolenie][ Znaleziony[pokolenie][0] ] = lista_kolejnych_krokow[i][0];
			
			Poprzednie_Pokolenie(pokolenie, lista_kolejnych_krokow[i][1] );
			
			Znaleziony[pokolenie][0]--;
			}
		
		}
	
	}
else if (pokolenie<minimalna_liczba_pokolen)
//else
	{//if pasujace>0
	int wskaz_pocz=wskaz_lista+1;
	int wskaz_kon;
	for (int komorka=1; komorka<=N; komorka++)
		{
		int k=pasujace;
		int jest_ok=1;
		
		for (int i=1; i<=podzialy[komorka][0]; i++)
			{
			k++;
			if (SZUKANY[k] != podzialy[komorka][i]) {jest_ok=0; break;}
			if (k==SZUKANY[0]) {jest_ok=2; break; }
			if (i==podzialy[komorka][0]) {jest_ok=1; break;}
			}
		
		if (jest_ok==2)
			{
			// Cały SZUKANY został znaleziony
			wskaz_lista++;
			lista_kolejnych_krokow[wskaz_lista][0]=komorka;
			lista_kolejnych_krokow[wskaz_lista][1]=-k;
//			printf("Weszlo do zakonczajacego Zbior\n");
			}
		if (jest_ok==1)
			{
			//Cała komórka wpasowuje się w szukany ciąg:
			wskaz_lista++;
			lista_kolejnych_krokow[wskaz_lista][0]=komorka;
			lista_kolejnych_krokow[wskaz_lista][1]=k;
//			printf("(Mozliwosc - komorka=%ld, k=%ld)",komorka,k);
			}
		}
	
	wskaz_kon=wskaz_lista;
	for (int i=wskaz_pocz; i<=wskaz_kon; i++)
		{
		if (lista_kolejnych_krokow[i][1]<0)
			{
			// Znaleziono komórkę zamykającą szukany ciąg
			Znaleziony[pokolenie][0]++;
			Znaleziony[pokolenie][ Znaleziony[pokolenie][0] ] = lista_kolejnych_krokow[i][0];
			
			// I jeszcze się upewnić, że chwilę wcześniej nie było identycznego...
			
			int juz_bylo=0;
			if (Znaleziony[pokolenie][0] == 2) //
				{
				if (Byla_PARA[ Znaleziony[pokolenie][1] ][ Znaleziony[pokolenie][2] ] == 1) juz_bylo=1;
				
				/*
				int bb=pokolenie;
				while (Znaleziony[bb-1][0]==Znaleziony[pokolenie][0])
					{
					if ((Znaleziony[bb-1][1]==Znaleziony[pokolenie][1]) && (Znaleziony[bb-1][2]==Znaleziony[pokolenie][2])) { juz_bylo=1; break; }
					bb--;
					}
				*/
				}
			if (juz_bylo==0)
				{
				// Tutaj mam pewność, że mogę iść dalej, bo wcześniej się nie powtórzyło
				int *w_SZUK;
				w_SZUK = new int[SZUKANY[0]+1];
				for (int yy=0; yy<=SZUKANY[0]; yy++) w_SZUK[yy]=SZUKANY[yy];
				
				if (Znaleziony[pokolenie][0]==2) Byla_PARA[ Znaleziony[pokolenie][1] ][ Znaleziony[pokolenie][2] ] = 1;
				else if (Znaleziony[pokolenie][0]==1) Byl_JEDEN[ Znaleziony[pokolenie][1] ] = 1;
				
				
				for (int yy=0; yy<=Znaleziony[pokolenie][0]; yy++) SZUKANY[yy]=Znaleziony[pokolenie][yy];
				Poprzednie_Pokolenie(pokolenie+1, 0);
				
				
				if (Znaleziony[pokolenie][0]==2) Byla_PARA[ Znaleziony[pokolenie][1] ][ Znaleziony[pokolenie][2] ] = 0;
				else if (Znaleziony[pokolenie][0]==1) Byl_JEDEN[ Znaleziony[pokolenie][1] ] = 0;
				
				for (int yy=0; yy<=w_SZUK[0]; yy++) SZUKANY[yy]=w_SZUK[yy];
				delete [] w_SZUK;
				}
			Znaleziony[pokolenie][0]--;
			}
		else //Czyli po prostu znaleziono fragment (dalszą część SZUKANEGO)
			{
			Znaleziony[pokolenie][0]++;
			Znaleziony[pokolenie][ Znaleziony[pokolenie][0] ] = lista_kolejnych_krokow[i][0];
			
			Poprzednie_Pokolenie(pokolenie, lista_kolejnych_krokow[i][1] );
			
			Znaleziony[pokolenie][0]--;
			}
		}
	}

return 0;
}


int main()
{
scanf("%ld %ld",&N,&M);
for (int i=1; i<=N; i++)
	{
	scanf("%ld",&podzialy[i][0]);
	for (int j=1; j<=podzialy[i][0]; j++) scanf("%ld",&podzialy[i][j]);
	}
for (int i=1; i<=M; i++) scanf("%ld",&dojrzaly[i]);



/*
char file_name[100];
int PRAWIDLOWY;

for (int zadanie=1; zadanie<=98; zadanie++)
{

sprintf(file_name,"eks%ld.in",zadanie);
printf("\n\nNazwa pliku: %s\n",file_name);

plik=fopen(file_name,"r");
fscanf(plik,"%ld %ld",&N,&M);
for (int i=1; i<=N; i++)
	{
	fscanf(plik,"%ld",&podzialy[i][0]);
	for (int j=1; j<=podzialy[i][0]; j++) fscanf(plik,"%ld",&podzialy[i][j]);
	}
for (int i=1; i<=M; i++) fscanf(plik,"%ld",&dojrzaly[i]);
fclose(plik);

minimalna_liczba_pokolen=1000000;
wskaz_lista=0;
*/


/////////////////////////////////////////////////////////////////////////////////
/*N=3; M=2;
podzialy[1][0]=2; podzialy[1][1]=2; podzialy[1][2]=3;
podzialy[2][0]=3; podzialy[2][1]=1; podzialy[2][2]=3; podzialy[2][3]=3;
podzialy[3][0]=2; podzialy[3][1]=1; podzialy[3][2]=2;
dojrzaly[1]=3; dojrzaly[2]=1;
////////////////////////////////////////////////////////////////////////////////*/
/*N=4; M=5;
podzialy[1][0]=3; podzialy[1][1]=2; podzialy[1][2]=4; podzialy[1][3]=2;
podzialy[2][0]=2; podzialy[2][1]=1; podzialy[2][2]=3;
podzialy[3][0]=2; podzialy[3][1]=1; podzialy[3][2]=2;
podzialy[4][0]=2; podzialy[4][1]=2; podzialy[4][2]=2;
dojrzaly[1]=4; dojrzaly[2]=2; dojrzaly[3]=1; dojrzaly[4]=3; dojrzaly[5]=1;
////////////////////////////////////////////////////////////////////////////////*/
/*N=3; M=4;
podzialy[1][0]=2; podzialy[1][1]=1; podzialy[1][2]=3;
podzialy[2][0]=2; podzialy[2][1]=3; podzialy[2][2]=2;
podzialy[3][0]=3; podzialy[3][1]=2; podzialy[3][2]=3; podzialy[3][3]=3;
dojrzaly[1]=3; dojrzaly[2]=3; dojrzaly[3]=2; dojrzaly[4]=1;
////////////////////////////////////////////////////////////////////////////////*/
/*N=3; M=4;
podzialy[1][0]=2; podzialy[1][1]=1; podzialy[1][2]=2;
podzialy[2][0]=2; podzialy[2][1]=3; podzialy[2][2]=2;
podzialy[3][0]=3; podzialy[3][1]=2; podzialy[3][2]=3; podzialy[3][3]=3;
dojrzaly[1]=3; dojrzaly[2]=3; dojrzaly[3]=2; dojrzaly[4]=1;
////////////////////////////////////////////////////////////////////////////////*/
/*N=3; M=4;
podzialy[1][0]=2; podzialy[1][1]=1; podzialy[1][2]=2;
podzialy[2][0]=2; podzialy[2][1]=3; podzialy[2][2]=2;
podzialy[3][0]=3; podzialy[3][1]=1; podzialy[3][2]=3; podzialy[3][3]=3;
dojrzaly[1]=3; dojrzaly[2]=3; dojrzaly[3]=2; dojrzaly[4]=1;
////////////////////////////////////////////////////////////////////////////////*/
////////////////////////////////////////////////////////////////////////////////*/
////////////////////////////////////////////////////////////////////////////////*/
////////////////////////////////////////////////////////////////////////////////*/


/*printf("N=%ld, M=%ld\n",N,M);
for (int i=1;i<=N; i++)
	{
	for (int j=1; j<=podzialy[i][0]; j++) printf("%ld ",podzialy[i][j]);
	printf("\n");
	}
printf("Dojrzaly:\n");
for (int i=1; i<=M; i++) printf("%ld ",dojrzaly[i]);
printf("\n");
*/

//Są dwie, raczej różne, możliwości:
// - dojrzały zawiera się w którymś z podziałów
// - dojrzały jest złożony z 2 lub więcej podziałów

// Możliwe zapętlenia:
// - całościowe (złożone z jednego): 
//    SZUKANY: 4
//    4) 1 2 4 1
// - podzielne (złożone z dwóch):
//    SZUKANY: 1 3
//    1) 1 1
//    3) 3 3
//
// Dłuższe niż 2 nie mogą się zapętlać... A więc maksymalna długość "wgłąb" to... 1000, ewentualnie dodatkowe 500-1000 na "pojedynczą ścieżkę"


// Żeby sprawdzić, czy się zawiera, sprawdzam długość, a następnie... Przyda się tablica przejść pi.
// Również sprawdzając, czy chociaż początek jest taki, jaki być powinien, to się przyda tablica przejść pi.

// Stworzenie tablicy pi dla Dojrzałego:


for (int i=1; i<=500; i++) for (int j=1; j<=500; j++) Byla_PARA[i][j]=0;
for (int i=1; i<=500; i++) Byl_JEDEN[i]=0;
for (int i=1; i<=M; i++) SZUKANY[i]=dojrzaly[i];
SZUKANY[0]=M;
for (int i=1; i<=2000; i++) Znaleziony[i][0]=0;



if ((M==1) && (dojrzaly[1]==1)) minimalna_liczba_pokolen=1;
else Poprzednie_Pokolenie(2, 0);


if (minimalna_liczba_pokolen==1000000) minimalna_liczba_pokolen=-1;
printf("%ld",minimalna_liczba_pokolen);


/*
sprintf(file_name,"eks%ld.out",zadanie);
plik=fopen(file_name,"r");
fscanf(plik,"%ld",&PRAWIDLOWY);
fclose(plik);

if (PRAWIDLOWY==minimalna_liczba_pokolen) printf("OK, %ld\n",PRAWIDLOWY);
else printf("!!!!!!!!!! BLAD !!!!!!!!!! PRAWIDLOWY=%ld, MOJ=%ld\n",PRAWIDLOWY,minimalna_liczba_pokolen);
printf("wskaz_lista=%ld\n",wskaz_lista);
//getch();
}
*/


//printf("\nPRZYWROCIC ZATRZYMYWANIE REKURENCJI\n");
//printf("\nSKASOWAC STRING.H I CONIO.H\n");

return 0;
}

