Cod sursa(job #3370184)

Utilizator TimofeiFilipTimofei Filip Emanuel TimofeiFilip Data 24 octombrie 2026 13:34:06
Problema PScPld Scor 20
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.09 kb
#include<bits/stdc++.h>
using namespace std;

const int NMAX = 1e5 + 10;
const int LOGMAX = 20;

typedef pair<int, int> pii;
typedef long long int ll;

ifstream fin("pscpld.in");
ofstream fout("pscpld.out");


int suffix[NMAX + 1][LOGMAX + 1];
string s;
int n;

struct Triplet {
    int index, left, right;
};
bool cmp(const Triplet &a, const Triplet &b) {
    if (a.left != b.left)
        return a.left < b.left;
    return a.right < b.right;
}

void compute_suffix() {
    for (int i = 0; i < n; i++)
        suffix[i][0] = s[i] - 'a';

    for (int j = 1; j <= LOGMAX; j++) {
        vector<Triplet> aux;
        for (int i = 0; i + (1 << j) - 1 < n; i++) {
            aux.push_back({
                i,
                suffix[i][j - 1],
                suffix[i + (1 << (j - 1))][j - 1]
            });
        }
        sort(aux.begin(), aux.end(), cmp);

        int rank = 0;

        for (int i = 0; i < aux.size(); i++) {
            if (i > 0 && (aux[i].left != aux[i - 1].left ||
                          aux[i].right != aux[i - 1].right)) {
                rank++;
                          }
            suffix[aux[i].index][j] = rank;
        }
    }
}
string mirror(const string &a) {
    string result = "";
    for (int i = a.size() - 1; i >= 0; i--) {
        result += a[i];
    }
    return result;
}
bool query(pii a, pii b) {
    if (a.second - a.first != b.second - b.first)
        return false;

    int len = a.second - a.first + 1;
    int log_query = 31 - __builtin_clz(len);

    bool left_son =
        suffix[a.first][log_query] ==
        suffix[b.first][log_query];

    bool right_son =
        suffix[a.second - (1 << log_query) + 1][log_query] ==
        suffix[b.second - (1 << log_query) + 1][log_query];

    return left_son && right_son;
}
int get_odd_palindrome(const int &m, const int center) {
    int left = 0;
    int right = center;
    int current_middle = -1;
    while (left <= right) {
        int middle = (left + right) / 2;
        int string_length = center - middle + 1;

        if (center + string_length > m) {
            left = middle + 1;
            continue;
        }

        int ans = query({middle, center}, {n - center - string_length, n - center - 1});
        //fout << middle << ' ' << center << ' ' << string_length << ' ' << ans <<'\n';
        //fout << middle << ' ' << center << ' ' << m - center - string_length << ' ' << m - center - 1 << '\n';
        if (ans) {
            current_middle = middle;
            right = middle - 1;
        }
        else
            left = middle + 1;
        // abaddaba
    }
    return current_middle == -1 ? 0 : (center - current_middle + 1);
}
int get_even_palindrome(const int &m, const int center) {
    if (center == m - 1) return 0;

    int left = 0;
    int right = center;

    int current_middle = -1;
    while (left <= right) {

        int middle = (left + right) / 2;

        int string_length = center - middle + 1;
        if (center + string_length > m) {
            left = middle + 1;
            continue;
        }

        int ans = query({middle, center}, {n - center - string_length - 1, n - center - 2});
        //fout << middle << ' ' << center << ' ' << string_length << ' ' << ans <<'\n';
        //fout << middle << ' ' << center << ' ' << n - center - string_length - 1 << ' ' << n - center - 2 << '\n';
        if (ans) {
            current_middle = middle;
            right = middle - 1;
        }
        else
            left = middle + 1;
        // abaddaba
    }
    //fout << current_middle << ' ' << center << '\n';
    return current_middle == -1 ? 0 : (center - current_middle + 1);
}
int main() {
    ios::sync_with_stdio(false);
    fin.tie(nullptr);
    fout.tie(nullptr);

    string original;
    fin >> original;

    int m = original.size();
    string reversed = original;
    reverse(reversed.begin(), reversed.end());

    s = original + reversed;
    n = s.size();

    compute_suffix();

    ll palindroame = 0;

    for (int center = 0; center < m; center++) {
        palindroame = palindroame + get_odd_palindrome(m, center) + get_even_palindrome(m, center);
    }

    fout << palindroame << '\n';
    return 0;
}