Cod sursa(job #669501)

Utilizator lily3Moldovan Liliana lily3 Data 27 ianuarie 2012 10:00:02
Problema Trie Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.81 kb
#include<stdio.h>
#define infile "trie.in"
#define outfile "trie.out"
#define nmax 512*1024
#define lmax 101
char v[lmax]; //vectorul in care citim liniile
struct nod
	{
	char c; //caracterul nodului
	int fi,fr; //pozitia fiu, respectiv frate
	int ap,ac; //numarul de aparitii pentru prefix, respectiv cuvant ce se termina aici
	} n[nmax]; //nodurile trie-ului
int nrn; //numarul de noduri ocupate

void add()
	{ //adaugam o aparitie a cuvantului in lista :P
	int i,j,k=0,r=0; //r-radacina arborelui (trie)
	for(i=2;v[i]&&v[i]!='\n';i++) //trebuie luate toate caracterele si puse in trie (daca nu exista)
		{
		for(j=n[r].fi;j;j=n[j].fr) //trecem pe la toti copii radacinei ;))
			if(n[j].c==v[i]) //am gasit caracterul ;))
				{
				n[j].ap++; //crestem numarul de aparitii pt prefix
				if(!v[i+1]||v[i+1]=='\n') n[j].ac++; //inseamna ca avem si o aparitie de cuvant :P
				r=j; //acest nod devine radacina pt nivelul urmator :P
				break; //am gasit...oprim cautarea:P
				}
			else k=j; //pt a sti fratele anterior daca nu gasim caracterul :P
		if(!j) //inseamna k nu am gasit...deci trebuie sa adaugam :P
			{
			nrn++; //facem loc pt noul nod
			n[nrn].c=v[i]; //salvam caracterul
			n[nrn].ap=1; //avem o aparitie pt prefix
			if(!v[i+1]||v[i+1]=='\n') n[nrn].ac=1; else n[nrn].ac=0; //daca se termina cuvant aici, sau nu
			if(!n[r].fi) n[r].fi=nrn; //inseamna ca tatal nu are niciun fiu, deci acesta va deveni fiu
			else n[k].fr=nrn; //altfel, ultimul frate, va avea legatura catre acest nou frate
			r=nrn; //acest nod va fi radacina pt nivelul urmator :P
			}
		}
	}

void del()
	{ //sterge o aparitie a cuvantului din lista
	int i,j,r=0; //r-radacina trie-ului
	for(i=2;v[i]&&v[i]!='\n';i++) //toate caracterele cuvantului
		for(j=n[r].fi;j;j=n[j].fr) //trecem pe la toti copii
			if(n[j].c==v[i]) //am gasit caracterul
				{
				n[j].ap--; //scadem prefixul
				if(!v[i+1]||v[i+1]=='\n') n[j].ac--; //se termina cuvantul...deci scadem si aparitia de cuvant ;))
				r=j; //se schimba radacina ;))
				break; //oprim cautarea mai departe
				}
	}

int ap()
	{ //returneaza numarul de aparitii ale cuvantului
	int i,j,r=0; //r-radacina :P
	for(i=2;v[i]&&v[i]!='\n';i++) //toate caracterele la rand
		{
		for(j=n[r].fi;j;j=n[j].fr) //trecem pe la toti fii radacinei
			if(n[j].c==v[i]&&n[j].ap) //inseamna ca am gasit caracterul de la aceasta pozitie
				{
				r=j; //se schimba radacina ;))
				if(!v[i+1]||v[i+1]=='\n') return n[r].ac; //returnam numarul de aparitii ale cuvantului
				break; //daca nu este inca sfarsitul cuvantului, oprim cautarea
				}
		if(!j) return 0; //inseamna ca nu am gasit, oprim cautarea si returnam 0
		}
	return 0; //nu a fost gasit ;))
	}

int lu()
	{ //returneaza lungimea celui mai lung prefix cu oricare alt cuvant din trie
	int i,j,r=0; //r-radacina trie-ului
	int l=0; //lungimea :P
	for(i=2;v[i]&&v[i]!='\n';i++) //luam toate caracterele
		{
		for(j=n[r].fi;j;j=n[j].fr) //trecem pe la toti copii
			if(n[j].c==v[i]&&n[j].ap) //am gasit caracter pe acest nivel
				{
				l++; //crestem lungimea
				r=j; //se schimba radacina ;))
				break; //oprim cautarea
				}
		if(!j) return l; //inseamna ca nu am gasit....deci afisem lungimea gasita pana acum ;))
		}
	return l; //in cazul in care a fost gasita in intregime ;))
	}

int main()
{
freopen(infile,"r",stdin);
freopen(outfile,"w",stdout);

while(fgets(v,lmax,stdin))
	{ //cat timp citim ;))
	if(v[0]=='0') add(); //adaugam o aparitie
	if(v[0]=='1') del(); //stergem o aparitie
	if(v[0]=='2') printf("%d\n",ap()); //afisem numarul de aparitii ale cuvantului
	if(v[0]=='3') printf("%d\n",lu()); //afisem cel mai lung prefix al sau cu oricare alt cuvant
	//for(int j=1;j<=nrn;++j)
		//printf("%c %d %d\n",n[j].c,n[j].fi,n[j].fr);
	//printf("\n");
	}


fclose(stdin);
fclose(stdout);
return 0;
}