제출 #1297246

#제출 시각아이디문제언어결과실행 시간메모리
1297246MisterReaperBrperm (RMI20_brperm)C++20
100 / 100
199 ms74680 KiB
#include "brperm.h"
#include "bits/stdc++.h"

namespace {
    using i64 = long long;

    template<typename T>
    T power(T a, i64 b) {
        T res = 1;
        while(b) {
            if(b & 1) {
                res *= a;
            }
            a *= a;
            b >>= 1;
        }
        return res;
    }
     
    constexpr int md = 998244353;
    struct MInt {
        int val;
        MInt() : val(0) {}
        template<typename T>
        MInt(T v) {
            if(-md <= v && v < md) {
                val = v;
            } else {
                val = v % md;
            }
            if(val < 0) {
                val += md;
            }
        }
        int operator() () { return val; }
        MInt operator+= (MInt rhs) {
            if((val += rhs.val) >= md) {
                val -= md;
            }
            return *this;
        }
        MInt operator-= (MInt rhs) {
            if((val -= rhs.val) < 0) {
                val += md;
            }
            return *this;
        }
        MInt operator*= (MInt rhs) {
            val = (int)(1LL * val * rhs.val % md);
            return *this;
        }
        MInt inv() {
            return power(*this, md - 2);
        }
        MInt operator/= (MInt rhs) {
            return *this *= rhs.inv();
        }
        bool operator== (MInt rhs) const {
            return val == rhs.val;
        }
        bool operator!= (MInt rhs) const {
            return val != rhs.val;
        }
    };
    MInt operator+ (MInt lhs, MInt rhs) {
        return lhs += rhs;
    }
    MInt operator- (MInt lhs, MInt rhs) {
        return lhs -= rhs;
    }
    MInt operator* (MInt lhs, MInt rhs) {
        return lhs *= rhs;
    }
    MInt operator/ (MInt lhs, MInt rhs) {
        return lhs /= rhs;
    }
    std::ostream& operator<< (std::ostream& os, MInt v) {
        return os << v();
    }
    std::string to_string(MInt x) {
        return to_string(x());
    }
     
    using Z = MInt;

    constexpr int base = 31;

    int N;
    int LG;
    std::string str;
    std::vector<Z> powb;
    std::vector<std::vector<Z>> pre;
    std::vector<std::vector<Z>> f;
};

void init(int n, const char s[]) {
    str = s;
    N = n;
    LG = std::__lg(N);
    powb.resize(LG + 1);
    powb[0] = base;
    for (int i = 1; i <= LG; ++i) {
        powb[i] = powb[i - 1] * powb[i - 1];
    }

    pre.resize(LG + 1);
    for (int j = 0; j <= LG; ++j) {
        pre[j].resize(N + 1);
        for (int i = 0; i < N; ++i) {
            pre[j][i + 1] = pre[j][i] * powb[LG - j] + (s[i] - 'a' + 1);
        }
    }

    f.resize(LG + 1);
    f[0].resize(N);
    for (int i = 0; i < N; ++i) {
        f[0][i] = s[i] - 'a' + 1;
    }
    for (int j = 1; j <= LG; ++j) {
        int m = N - (1 << j) + 1;
        f[j].resize(m);
        for (int i = 0; i < m; ++i) {
            f[j][i] = powb[LG - j] * f[j - 1][i] + f[j - 1][i + (1 << (j - 1))];
        }
    }

    // for (int j = 0; j <= LG; ++j) {
    //     int m = N - (1 << j) + 1;
    //     for (int i = 0; i < m; ++i) {
    //         std::cerr << f[j][i] << " \n"[i == m - 1];
    //     }
    // }

    return;
}

int query(int i, int k) {
    if (i + (1 << k) - 1 >= N) {
        return 0;
    }
    Z sh = pre[k][i + (1 << k)] - pre[k][i] * powb[LG];
    // Z sh = 0;
    // for (int j = 0; j < (1 << k); ++j) {
    //     sh = sh * powb[LG - k] + str[i + j] - 'a' + 1;
    //     std::cerr << sh << ' ';
    // }
    // std::cerr << '\n';
    Z rh = f[k][i];
    // std::cerr << "[sh, rh]: " << sh << ' ' << rh << '\n';
    return sh == rh;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...