Cod sursa(job #771125)

Utilizator GagosGagos Radu Vasile Gagos Data 24 iulie 2012 21:00:57
Problema Trie Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.07 kb
#include <cstdio>
#include <cstring>

class Trie {
 public:
  class Node {
   public:
    Node(bool word_stop = false);

    int number_of_words();
    void remove_son(char son);
    Node* add_son(char son, bool mark_as_word = false);

    Node* operator[](const char& son) const;

   private:
    int word_count_;
    Node* sons_[26];

    bool has_sons();
    bool is_word();
    void mark_as_word();
    void de_mark();
  };

  Trie();

  int length_of_longest_prefix(char* word);
  int times_word_appears(char* word);
  void add_word(char* word);
  void remove_word(char* word);

 private:
  Node* root_;

  int length_of_longest_prefix(char* word, Node* node, int level = -1);
  int times_word_appears(char* word, Node* node);
  void add_word(char* word, Node* node);
  void remove_word(char* word, Node* node);
};

Trie::Node::Node(bool word_stop) {
  this->word_count_ = word_stop ? 1 : 0;
}

Trie::Node* Trie::Node::operator[](const char& son) const {
  char chr = son | 32;

  if (chr >= 'a' && chr <= 'z') {
    return this->sons_[chr - 'a'];
  }

  return NULL;
}

int Trie::Node::number_of_words() {
  return this->word_count_;
}

Trie::Node* Trie::Node::add_son(char son, bool mark_as_word) {
  char chr = son | 32;
  int index;

  if (chr < 'a' || chr > 'z') {
    return NULL;
  }

  index = chr - 'a';

  if (this->sons_[index] == NULL) {
    this->sons_[index] = new Node(mark_as_word);
  } else {
    if (mark_as_word) {
      this->sons_[index]->mark_as_word();
    }
  }

  return this->sons_[index];
}

void Trie::Node::remove_son(char son) {
  char chr = son | 32;
  int index;
  Node* the_son;

  if (chr < 'a' || chr > 'z') {
    return;
  }

  index = chr - 'a';
  the_son = this->sons_[index];

  if (the_son != NULL) {
    the_son->de_mark();

    if (!the_son->is_word() && !the_son->has_sons()) {
      this->sons_[index] = NULL;

      delete the_son;
    }
  }
}

bool Trie::Node::has_sons() {
  for(int i = 0; i < 26; ++i) {
    if (this->sons_[i] != NULL) {
      return true;
    }
  }

  return false;
}

bool Trie::Node::is_word() {
  return this->word_count_ > 0;
}

void Trie::Node::mark_as_word() {
  this->word_count_ += 1;
}

void Trie::Node::de_mark() {
  this->word_count_ -= this->is_word() ? 1 : 0;
}

Trie::Trie() {
  this->root_ = new Node();
}

void Trie::add_word(char* word) {
  this->add_word(word, this->root_);
}

void Trie::add_word(char* word, Node* node) {
  if (strlen(word) == 1) {
    node->add_son(word[0], true);
    return;
  }

  this->add_word(word + 1, node->add_son(word[0]));
}

void Trie::remove_word(char* word) {
  this->remove_word(word, this->root_);
}

void Trie::remove_word(char* word, Node* node) {
  if (node == NULL) {
    return;
  }

  if (strlen(word) == 1) {
    node->remove_son(word[0]);
    return;
  }

  this->remove_word(word + 1, (*node)[word[0]]);
  node->remove_son(word[0]);
}

int Trie::times_word_appears(char* word) {
  return this->times_word_appears(word, this->root_);
}

int Trie::times_word_appears(char* word, Node* node) {
  if (node == NULL) {
    return 0;
  }

  if (strlen(word) == 1) {
    return (*node)[word[0]]->number_of_words();
  }

  return this->times_word_appears(word + 1, (*node)[word[0]]);
}

int Trie::length_of_longest_prefix(char* word) {
  return this->length_of_longest_prefix(word, this->root_);
}

int Trie::length_of_longest_prefix(char* word, Node* node, int level) {
  if (node == NULL) {
    return level;
  }

  return this->length_of_longest_prefix(word + 1, (*node)[word[0]], level + 1);
}

int main() {
  Trie trie;
  int op;
  char str[23];

  freopen("trie.in", "r", stdin);
  freopen("trie.out", "w", stdout);

  while(!feof(stdin)) {
    memset(str, 0, 23 * sizeof(char));
    scanf("%d %s", &op, str);

    switch(op) {
      case 0: {
        trie.add_word(str);
        break;
      }
      case 1: {
        trie.remove_word(str);
        break;
      }
      case 2: {
        printf("%d\n", trie.times_word_appears(str));
        break;
      }
      case 3: {
        printf("%d\n", trie.length_of_longest_prefix(str));
        break;
      }
      default: {
        break;
      }
    }
  }

  fcloseall();

  return 0;
}