Cod sursa(job #2731714)

Utilizator om6gaLungu Adrian om6ga Data 28 martie 2021 02:21:40
Problema Trie Scor 100
Compilator c-32 Status done
Runda Arhiva educationala Marime 3.77 kb
#include <stdio.h>
#include <stdlib.h>
 
#define CH (*s - 'a')
 
struct TrieNode {
	struct TrieNode *parent;
	struct TrieNode *child[26];
	char childrenCount; // useful for deletion
	short int freq; // nr of appearances of the word formed by the characters belonging to the path starting at root and ending here
};
typedef struct TrieNode TrieNode;
 
TrieNode mem[115000]; // chunk of 120000 nodes
TrieNode *free_index[115000];
int first_free_index;
int alloc_cnt = 1;
TrieNode *T = mem;  // first node in chunk we'll be using as root
int ch, isnull, t;
char output[200000];
int oindex;
char input[2000000];
int iindex;

 
void add(TrieNode *node, char *s) {  // assume word '\0' terminated
	while (1) {
		ch = *s - 'a';
		if (s[0] == '\0') { 
			node->freq++;
		    return;
		}
		isnull = (node->child[ch] == NULL);
		node->childrenCount += isnull;
		node->child[ch] = (isnull ? free_index[first_free_index--] : node->child[ch]);
		node->child[ch]->parent = (isnull ? node : node->child[ch]->parent);
		node = node->child[ch];
		s++;
	}
}
 
void rm(TrieNode *node, char *s) {
	while (1) {
		if (s[0] == '\0') { 
		    node->freq--; /* we're guaranteed to find the element on remove op so no need to test freq here */
		    node = ((node->freq == 0 && node->childrenCount == 0) ? node->parent : NULL);
		    break;
		}
		node = node->child[CH];
		s++;
	}
	s--;
	/* go back up the tree and see which other nodes need to be remove (if any)*/
	while (node != NULL) {
		ch = *s - 'a';
		free_index[++first_free_index] = node->child[CH];
		node->child[CH] = 0;
		node->childrenCount--;
		node = ((node->freq == 0 && node->childrenCount == 0) ? node->parent : NULL);
		s--;
	}
}
 
int query(TrieNode *node, char *s) {
	while (1) {
		if (s[0] == '\0')
		    return node->freq;
		node = node->child[CH];
	    if (node == NULL)
	        return 0;
	    s++;
	}
	return 0;
}

int prefix(TrieNode *node, char *s) {	 
    t = 0;
	while (1) {
		node = node->child[CH];
		if (!node || s[0] == '\0')
		    return t;
		s++;
		t++;
	}
}
 
void inorder(TrieNode *node, char *buf, int k) {
	int i;
	
	if (node->freq > 0) {
		buf[k] = '\0';
		printf("%s\n", buf);
	}
	for (i = 0; i < 26; i++)
	    if (node->child[i]) {
	    	buf[k] = i+'a';
	    	inorder(node->child[i], buf, k+1);
		}
}
 
int main() {
	char *s, op;
	int i = 0, nr, j = 0;
 
    freopen( "trie.in", "r", stdin );
	freopen( "trie.out", "w", stdout );
	//freopen( "grader_test20.in", "r", stdin );
	//freopen( "grader_test20.out", "w", stdout );
	iindex = read(0, input, 2000000);

    /* using index 0 in mem[] for root, put the rest in free_index[]; do this in an attempt to somewhat speculate
	   cache locality ... instead of advancing towards the end of the array with each new node, try to reuse the freed ones */
    for (i = 114999; i>=1; i--)
        free_index[j++] = &mem[i];
    first_free_index = j-1; 

	while (1) {
		op = input[i];
		s = input+i+2;
		i += 3;
		for (;;) {
			if (input[i] == '\n')
			    break;
			i++;
		}
		input[i++] = '\0';
		switch(op) {
			case '0':
				add(T, s);
			    break;
			case '1':
				rm(T, s);
			    break;
			case '2':
				nr = query(T, s);
				oindex += sprintf(output+oindex, "%d\n", nr);
			    break;
			case '3':
				nr = prefix(T, s);
				oindex += sprintf(output+oindex, "%d\n", nr);
			    break;
		}
		if (i >= iindex)
	        break;
	}
	write(1, output, oindex);
	//inorder(T, buf, 0);
	return 0;
}

/*
int rm_rec(TrieNode *node, char *s) {
	if  (s[0] < 'a') {
        node->freq--;
	}
	else if (rm_rec(node->child[CH], s+1)) {
		node->child[CH] = 0;
		node->childrenCount--;
	}
	if (node->freq == 0 && node->childrenCount == 0 && node != T) {
		//free(node);
		return 1;
	}
	return 0;
}
*/