/*
	Uobicajeno usporedivanje studenata moze biti presporo ako
	je zadan velik broj studenata. Zato je uz svaku grupu rijeci
	(uz svakog studenta) zapisan po jedan broj koji je nekako
	izracunat iz pripadajucih rijeci.
	Nakon toga, dovoljno je samo usporedivati brojeve pridruzene
	studentima. Ako se pripadajuci brojevi nekih studenata
	razlikuju onda oni sigurno nemaju iste rijeci. Ako su im brojevi
	isti, onda jos postoji mogucnost da su te grupe rijeci slucajno
	dobile isti broj, pa se onda ipak za takve studente treba posebno
	provjeriti da li su identicni. Opisanim postupkom se znatno
	smanji broj usporedivanja rijeci, pa se i brzina izvodenja
	programa povecava.

	Dodatno, svaki student za kojeg se ustanovi da je neciji 'duplikat'
	oznaci se tako da se vise ne gleda.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXSTUD 4000
#define MAXPRED 3
#define MAXRIJEC 10

int stud;
int pred[MAXSTUD];               // broj predmeta(rijeci) pojedinog studenta
char huge rijec[MAXSTUD][MAXPRED][MAXRIJEC+1];         // rijeci
int broj[MAXSTUD];               // broj pridruzen studentu
int duplikat[MAXSTUD];           // oznaka da li je student duplikat

int isto(int a, int b) /* usporedba studenta a i b */
{
	/*
	Funkcija se poziva samo ako oba studenta imaju isti broj rijeci.
	Svaka rijec prvog studenta trazi se medu rijecima drugog, ako se
	sve nadu znaci da su studenti 'isti'.
	Moze se izvesti i brze, ali nije potrebno posto se ne poziva cesto.
	*/
	int i, j, ok;
	for (i=0; i<pred[a]; i++)
	{       ok = 0;
		for (j=0; j<pred[b] && !ok; j++)
			if (strcmp((char *)rijec[a][i],(char *)rijec[b][j])==0)
				ok = 1;
		if (!ok) return 0; // studenti su razliciti
	}
	return 1; // studenti imaju iste skupove rijeci
}

int main()
{
	FILE *f;
	char str[80];
	int i, j, k, l, b, razlicitih;

	/* citanje rijeci iz datoteke */

	f = fopen("ukusi.in", "rt");
	fscanf(f, "%d\n", &stud);
	for (i=0; i<stud; i++)
	{	fgets(str, 80, f);
		pred[i]=sscanf(str,"%s%s%s",rijec[i][0],rijec[i][1],rijec[i][2]);
	}
	fclose(f);

	/* racunanje pripadajucih brojeva */

	for (i=0; i<stud; i++)
	{
		/*
		Uz nesto isprobavanja, moze se odrediti neka
		funkcija po kojoj se izracuna pripadajuci broj,
		tako da se za iste skupove rijeci uvijek dobije
		isti broj, a da se za razlicite skupove sto cesce
		dobiju razliciti brojevi.
		*/
		broj[i] = 0;
		for (j=0; j<pred[i]; j++)
		{       l = strlen((char *)rijec[i][j]);
			b = rijec[i][j][0];
			for (k=1; k<l; k++)
				b += (long)k*k*(rijec[i][j][k])*(rijec[i][j][k])*(rijec[i][j][k-1]);
			broj[i] += b;
		}
		/*
		Neka jednostavnija funkcije (npr. zbroj slova
		svih rijeci) bi se isto mogla koristiti, ali
		bi onda bilo puno vise razlicitih skupova koji bi
		dobili isti broj, pa bi trebalo provesti puno
		vise usporedivanja studenata.
		*/
	}

	/*
	Za svaka dva studenta gleda sa da li imaju isti pridruzeni
	broj i isti broj rijeci. Ako imaju, onda im se usporeduju
	rijeci, i ako su iste onda se student s vecim brojem oznaci
	kao duplikat.
	*/

	for (i=0; i<stud; i++) duplikat[i] = 0;

	for (i=0; i<stud-1; i++) if (!duplikat[i])
		for (j=i+1; j<stud; j++) if (!duplikat[j])
			if (broj[i]==broj[j] && pred[i]==pred[j])
				if (isto(i, j))
					duplikat[j] = 1;

	/*
	Broj studenata koji nisu oznaceni kao dupli je broj
	razliciti ukusa.
	*/

	razlicitih = 0;
	for (i=0; i<stud; i++)
		if (!duplikat[i]) razlicitih++;
	f = fopen("ukusi.out", "wt");
	fprintf(f, "%d\n", razlicitih);
	fclose(f);
	return 0;
}

