Cod sursa(job #3120847)

Utilizator GabiTulbaGabi Tulba-Lecu GabiTulba Data 8 aprilie 2023 22:57:48
Problema PScPld Scor 50
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.72 kb
#include <cstdio>
#include <map>
#include <string>

using namespace std;

const int max_len = 1e6;

class PalindromicTree {
    class Node {
      public:
        int length;
        int visit_cnt;
        Node *suffix;
        map<int, Node *> next;

        Node(int length) {
            this->length = length;
            visit_cnt = 0;
            suffix = NULL;
        }
        ~Node() {
            for (auto entry : next) {
                delete entry.second;
            }
            next.clear();
        }
    };

  public:
    string str;
    Node *odd_root;
    Node *even_root;
    Node *curr_node;

    PalindromicTree() {
        // initialize the roots of the tree
        odd_root = new Node(-1);
        even_root = new Node(0);
        odd_root->suffix = odd_root;
        even_root->suffix = odd_root;
        curr_node = odd_root;
    }

    ~PalindromicTree() {
        delete odd_root;
        delete even_root;
        even_root = odd_root = NULL;
    }

    int add_chr(char ch) {
        str.push_back(ch);
        int idx = ch - 'a';

        // while we can't extend the current palindrome we move to the next
        // suffix
        while ((int)str.size() - 2 - curr_node->length < 0 ||
               str[str.size() - 2 - curr_node->length] != ch) {
            curr_node = curr_node->suffix;
        }

        // if there's already a node there we don't do anything
        if (curr_node->next.find(idx) != curr_node->next.end()) {
            curr_node = curr_node->next[idx];
            return curr_node->visit_cnt;
        }

        // otherwise, we create a node that is the son of the current node
        Node *new_node = new Node(curr_node->length + 2);
        curr_node->next[idx] = new_node;

        // if the length is 1, the suffix will be the even root
        if (new_node->length == 1) {
            new_node->suffix = even_root;
            new_node->visit_cnt = 1;
            curr_node = new_node;
            return new_node->visit_cnt;
        }

        // we now compute the suffix of the new node
        curr_node = curr_node->suffix;
        while ((int)str.size() - 2 - curr_node->length < 0 ||
               str[str.size() - 2 - curr_node->length] != ch) {
            curr_node = curr_node->suffix;
        }
        new_node->suffix = curr_node->next[idx];
        new_node->visit_cnt = 1 + new_node->suffix->visit_cnt;

        curr_node = new_node;
        return curr_node->visit_cnt;
    }
};

int main() {
    freopen("pscpld.in", "r", stdin);
    freopen("pscpld.out", "w", stdout);

    long long ans = 0;
    PalindromicTree T;

    char str[max_len + 1];
    scanf("%s", str);

    for (int i = 0; str[i] != '\0'; i++) {
        ans += T.add_chr(str[i]);
    }

    printf("%lld\n", ans);
    return 0;
}