Cod sursa(job #1526778)

Utilizator paul-gPaul Grigoras paul-g Data 17 noiembrie 2015 11:33:18
Problema Trie Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 3.29 kb
// (a..z) --> Nodes
// Terminating character
// ab aba
// a -> b (null)
// a -> b (1) -> a (1)
//
// a -> b -> a (null)

#include <string>
#include <fstream>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

const int alpha = 'z' - 'a' + 1;

struct Node {
  int count;
  Node* cs[alpha];

  Node() {
    count = 0;
    memset(cs, 0, sizeof(Node*) * alpha);
  }

  Node* get_node(char c) {
    return cs[c - 'a'];
  }

  void set_node(char c, Node *n) {
    Node* old = cs[c - 'a'];
    if (old == NULL && n != NULL)
      n_children++;
    else if (old != NULL && n == NULL)
      n_children--;
    cs[c - 'a'] = n;
  }

  int children() {
    return n_children;
  }

  private:
  int n_children;
};

class Trie {

  public:
    Node* root;
    Trie() {
      root = new Node();
    }

    Node* insert2(const string& w, Node *crt, int pos) {
      char c = w[pos];
      Node* nxt = crt->get_node(c);
      if (nxt == NULL) {
        nxt = new Node();
        crt->set_node(c, nxt);
      }
      if (w.size() - 1 == pos) {
        nxt->count++;
        return crt;
      }
      crt->set_node(c, insert2(w, nxt, pos + 1));
      return crt;
    }

    void insert(const string& w) {
      //std::cout << "::insert" << std::endl;
      insert2(w, root, 0);
    }

    string lcp2(const string& w, Node * n, int pos) {
      if (pos == w.size())
        return "";
      Node* nxt = n->get_node(w[pos]);
      if (nxt == NULL)
        return "";
      return w[pos] + lcp2(w, nxt, pos + 1);
    }

    string lcp(const string& w) {
      return lcp2(w, root, 0);
    }

    int count2(const string& w, Node* crt, int pos) {
      Node* nxt = crt->get_node(w[pos]);
      if (nxt == NULL)
        return 0;
      if (pos == w.size() - 1)
        return nxt->count;
      return count2(w, nxt, pos + 1);
    }

    int count(const string& w) {
      return count2(w, root, 0);
    }

    void del(const string& w) {
      if (del_rec(w, root, 0) == NULL)
        root = new Node();
    }

    Node* del_rec(const string& w, Node* n, int pos) {
      char c = w[pos];
      //std::cout << "char = " << c << " del " << std::endl;
      Node* nxt = n->get_node(c);
      if (pos == w.size() - 1) {
        nxt->count--;
        if (nxt->count > 0) {
          //std::cout << "Not deleting" << std::endl;
          return n;
        }
        if (nxt->children() == 0 ) {
          //std::cout << "Delete" << std::endl;
          delete nxt;
          n->set_node(c, NULL);
        }
      } else
        n->set_node(c, del_rec(w, nxt, pos + 1));
      if (n->children() == 0 && n->count == 0) {
        //std::cout << "char = " << c << " deleting stuff" << std::endl;
        delete n;
        return NULL;
      }
      return n;
    }

};


int main () {
  ifstream f("trie.in");
  ofstream g("trie.out");
  int a;
  string s;
  Trie t;
  int line = 0;
  while (f >> a) {
    f >> s;
    line++;
    //std::cout << line << " " << s << std::endl;
    switch (a) {
      case 0:
        t.insert(s);
        break;
      case 1:
        t.del(s);
        break;
      case 2:
        g << t.count(s) << endl;
        break;
      case 3:
        string l = t.lcp(s);
        //std::cout << "prefix " << l << std::endl;
        //std::cout << "P" << std::endl;
        g << l.size() << endl;
        break;
    }
  }
}