結果

問題 No.263 Common Palindromes Extra
ユーザー amesyuamesyu
提出日時 2024-10-24 16:42:12
言語 C++17(clang)
(17.0.6 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 4,873 bytes
コンパイル時間 7,172 ms
コンパイル使用メモリ 172,160 KB
実行使用メモリ 104,460 KB
最終ジャッジ日時 2024-10-24 16:42:24
合計ジャッジ時間 9,285 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 223 ms
22,716 KB
testcase_01 AC 11 ms
7,400 KB
testcase_02 AC 14 ms
7,552 KB
testcase_03 AC 682 ms
31,484 KB
testcase_04 TLE -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
using namespace std;

const long long MOD = 10000000000000099;
const long long BASE = 1333;
const int MAXN = 5 * 100000;

long long POWER[MAXN + 1];

long long mul(long long a, long long b) {
    return ((__int128_t)a * b) % MOD;
}

class RollingHash {
public:
    RollingHash(const string& s) : size(s.size()), str(s) {
        hashed.resize(size + 1);
        for (int i = 0; i < size; ++i) {
            hashed[i + 1] = mul(hashed[i], BASE) + (s[i]);
            hashed[i + 1] %= MOD;
        }
    }

    long long query(int l, int r) {
        assert(0 <= l && l <= r && r <= size);
        return (hashed[r] - mul(hashed[l], POWER[r - l]) + MOD) % MOD;
    }

private:
    string str;
    vector<long long> hashed;
    int size;
};

class Eertree {
public:
    Eertree(const string& s) : str(s), size(s.size()), r1(s), r2(string(s.rbegin(), s.rend())) {}

    void build() {
        const int BEGIN = 'A'; // or 'a'
        const int PALINDROME_SIZE = 2 * size;
        vector<vector<int>> G(PALINDROME_SIZE);
        H.resize(PALINDROME_SIZE);
        W.resize(PALINDROME_SIZE, 0);
        vector<unordered_map<long long, int>> ptr(27);
        
        ptr[26][0] = 0;
        H[0] = {26, 0};
        int free = 1;

        for (int i = 0; i < size; ++i) {
            int ID = str[i] - BEGIN;
            int ok = -1, ng = min(i, size - i - 1) + 1;

            while (ng - ok > 1) {
                int x = (ng + ok) >> 1;
                long long h1 = r1.query(i + 1, i + 1 + x);
                long long h2 = r2.query(size - i, size - i + x);
                if (ptr[ID].count(h1) && ptr[ID][h1] >= 0 && h1 == h2) ok = x;
                else ng = x;
            }

            if (ok == -1) {
                ptr[ID][0] = free;
                H[free] = {ID, 0};
                free++;
                ok = 0;
            }

            int par = ptr[ID][r1.query(i + 1, i + 1 + ok)];
            for (int j = ok + 1; j < min(i + 1, size - i); ++j) {
                if (str[i + j] == str[i - j]) {
                    long long h1 = r1.query(i + 1, i + j + 1);
                    ptr[ID][h1] = free;
                    G[par].push_back(free);
                    H[free] = {ID, h1};
                    par = free;
                    free++;
                } else {
                    break;
                }
            }
            W[par] += 1;

            // Centroid = ''
            ok = 0;
            ng = min(i, size - i - 1) + 1;
            ID = 26;

            while (ng - ok > 1) {
                int x = (ng + ok) >> 1;
                long long h1 = r1.query(i, i + x);
                long long h2 = r2.query(size - i, size - i + x);
                if (ptr[ID].count(h1) && ptr[ID][h1] >= 0 && h1 == h2) ok = x;
                else ng = x;
            }

            par = ptr[ID][r1.query(i, i + ok)];
            for (int j = ok + 1; j < min(i + 1, size - i + 1); ++j) {
                if (str[i + j - 1] == str[i - j]) {
                    long long h1 = r1.query(i, i + j);
                    ptr[ID][h1] = free;
                    G[par].push_back(free);
                    H[free] = {ID, h1};
                    par = free;
                    free++;
                } else {
                    break;
                }
            }
            W[par] += 1;
        }

        function<long long(int)> dfs = [&](int v) {
            for (int nxt : G[v]) {
                W[v] += dfs(nxt);
            }
            return W[v];
        };

        for (int ID = 0; ID < 27; ++ID) {
            if (ptr[ID].count(0) && ptr[ID][0] >= 0) dfs(ptr[ID][0]);
        }
        W[0] = 0;
    }

    vector<long long> getW() const { return W; }
    vector<pair<int, long long>> getH() const { return H; }

private:
    string str;
    int size;
    RollingHash r1, r2;
    vector<long long> W;
    vector<pair<int, long long>> H;
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    for (int i = 0; i <= MAXN; ++i) {
        POWER[i] = (i == 0) ? 1 : mul(POWER[i - 1], BASE);
    }

    string s, t;
    cin >> s >> t;

    Eertree palS(s);
    Eertree palT(t);
    palS.build();
    palT.build();

    vector<long long> SW = palS.getW();
    vector<long long> TW = palT.getW();
    vector<pair<int, long long>> SH = palS.getH();
    vector<pair<int, long long>> TH = palT.getH();

    unordered_map<long long, array<long long, 2>> pair;
    
    for (size_t i = 0; i < SW.size(); ++i) {
        pair[SH[i].first*MOD+SH[i].second][0] += SW[i];
    }
    for (size_t i = 0; i < TW.size(); ++i) {
        pair[TH[i].first*MOD+TH[i].second][1] += TW[i];
    }

    long long ans = 0;
    for (const auto& p : pair) {
        ans += p.second[0] * p.second[1];
    }

    cout << ans << '\n';
    return 0;
}


0