Pagini recente » Cod sursa (job #2976249) | Cod sursa (job #673214) | Cod sursa (job #320249) | Cod sursa (job #2560238) | Cod sursa (job #2731912)
#include <stdio.h>
#include <stdlib.h>
#define CH (*s - 'a')
struct TrieNode {
struct TrieNode *child[26];
char childrenCount; // useful for deletion
char 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;
int dbg_flag;
static inline 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 = node->child[ch];
s++;
}
}
TrieNode *path[64];
int path_members;
static inline void rm(TrieNode *node, char *s) {
path_members = 0;
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 */
break;
}
node = node->child[CH];
path[path_members++] = node;
s++;
}
s--;
while (path_members >= 0) {
node = path[--path_members];
ch = *s - 'a';
node->child[CH] = 0;
node->childrenCount--;
if (node->freq || node->childrenCount){
return;
}
free_index[++first_free_index] = node;
s--;
}
}
static inline int query(TrieNode *node, char *s) {
if (dbg_flag) printf("query(%s)\n", s);
while (1) {
if (s[0] == '\0')
return node->freq;
node = node->child[CH];
if (node == NULL)
return 0;
s++;
}
return 0;
}
static inline int prefix(TrieNode *node, char *s) {
t = 0;
if (dbg_flag) printf("prefix(%s)\n", s);
while (1) {
node = node->child[CH];
if (!node || s[0] == '\0')
return t;
s++;
t++;
}
}
static inline 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 marching towards the end of the array with each new node, try to reuse the
previously 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;
while (1) {
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;
}
*/