답안 #344497

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
344497 2021-01-06T03:02:16 Z 12tqian 회문 (APIO14_palindrome) C++17
100 / 100
518 ms 63788 KB
#include <bits/stdc++.h>
using namespace std;
 
#define f1r(i, a, b) for (int i = a; i < b; i++) 
#define f0r(i, a) f1r(i, 0, a)
#define eb emplace_back
#define pb push_back
#define f first
#define s second
#define mp make_pair
#define sz(x) (int) (x).size()
#define all(x) (x).begin(), (x).end()
 
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pi;
typedef vector<pi> vpi;
 
 
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define F0R(i, a) FOR(i,0,a)
#define ROF(i, a, b) for (int i = (b) - 1; i >= (a); --i)
#define R0F(i, a) ROF(i, 0, a)
#define trav(a, x) for (auto& a : x)
typedef string str;
template <class T> struct SparseTable {
    std::vector<T> v;
    std::vector<std::vector<int>> jump;
    int level(int x) {
        return 31 - __builtin_clz(x);
    }
    int comb(int a, int b) {
        return v[a] == v[b] ? std::min(a, b) : (v[a] < v[b] ? a : b);
    }
    void init(const std::vector<T>& _v) {
        v = _v;
        jump = {std::vector<int>((int) v.size())};
        iota(jump[0].begin(), jump[0].end(), 0);
        for (int j = 1; (1 << j) <= (int) v.size(); j++) {
            jump.push_back(std::vector<int>((int) v.size() - (1 << j) + 1));
            for (int i = 0; i < (int) jump[j].size(); i++) {
                jump[j][i] = comb(jump[j - 1][i], jump[j - 1][i + (1 << (j - 1))]);
            }
        }
    }
    int index(int l, int r) {
        assert(l <= r);
        int d = level(r - l + 1);
        return comb(jump[d][l], jump[d][r - (1 << d) + 1]);
    }
    T query(int l, int r) {
        return v[index(l, r)];
    }
};

struct SuffixArray {
    std::string s;
    int n;
    std::vector<int> sa, isa, lcp;
    SparseTable<int> S;
    void init(string _s) {
        n = (int) (s = _s).size() + 1;
        gen_suffix_array();
        gen_lcp_array();
    }
    void gen_suffix_array() {
        sa = isa = std::vector<int>(n);
        sa[0] = n - 1;
        iota(1 + sa.begin(), sa.end(), 0);
        sort(1 + sa.begin(), sa.end(), [&](int a, int b) {
            return s[a] < s[b];
        });
        for (int i = 1; i < n; i++) {
            int a = sa[i - 1], b = sa[i];
            isa[b] = i > 1 && s[a] == s[b] ? isa[a] : i;
        }
        for (int len = 1; len < n; len *= 2) {
            std::vector<int> ss(sa), is(isa), pos(n);
            iota(pos.begin(), pos.end(), 0);
            for (auto& t : ss) {
                int tt = t - len;
                if (tt >= 0) 
                    sa[pos[isa[tt]]++] = tt;
            }
            for (int i = 1; i < n; i++) {
                int a = sa[i - 1], b = sa[i];
                isa[b] = is[a] == is[b] && is[a + len] == is[b + len] ? isa[a] : i;
            }
        }
    }
    void gen_lcp_array() {
        lcp = std::vector<int>(n - 1);
        int h = 0;
        for (int b = 0; b < n - 1; b++) {
            int a = sa[isa[b] - 1];
            while (a + h < (int) s.size() && s[a + h] == s[b + h]) 
                h++;
            lcp[isa[b] - 1] = h;
            if (h) h--;
        }
        S.init(lcp);
    }
    int get_lcp(int a, int b) {
        if (a == b) {
            return (int) s.size() - a;
        }
        int l = isa[a], r = isa[b]; 
        if (l > r) swap(l, r);
        return S.query(l, r - 1);
    }
};
 
std::vector<int> manacher(std::string s) {
    std::string t = "@";
    for (auto& c : s) 
        t += c, t += '#';
    t.back() = '&';
    std::vector<int> res((int) t.size() - 1);
    int lo = 0, hi = 0;
    for (int i = 1; i < (int) t.size() - 1; i++) {
        if (i != 1)
            res[i] = std::min(hi - i, res[hi - i + lo]);
        while (t[i - res[i] - 1] == t[i + res[i] + 1])
            res[i]++;
        if (i + res[i] > hi)
            lo = i - res[i], hi = i + res[i];
    }
    res.erase(res.begin());
    for (int i = 0; i < (int) res.size(); i++)
        if ((i & 1) == (res[i] & 1))
            res[i]++;
    return res;
}

struct IntervalJoin {
    std::vector<int> e;
    std::vector<std::pair<int, int>> interval;
    void init(int n) {
        e = std::vector<int>(n, -1);
        interval.resize(n);
        for (int i = 0; i < n; i++) {
            interval[i].first = interval[i].second = i;
        }
    }
    int get(int x) {
        return e[x] < 0 ? x : e[x] = get(e[x]);
    }
    bool same_set(int a, int b) {
        return get(a) == get(b);
    }
    int size(int x) {
        return -e[get(x)];
    }
    bool unite(int x, int y) {
        x = get(x), y = get(y);
        if (x == y) return false;
        if (e[x] > e[y]) std::swap(x, y);
        interval[x].first = min(interval[x].first, interval[y].first);
        interval[x].second = max(interval[x].second, interval[y].second);
        e[x] += e[y]; e[y] = x;
        return true;
    }
    std::pair<int, int> get_interval(int x) {
        x = get(x);
        return interval[x];
    }
};
 
template <class T> struct BIT {
    std::vector<T> bit;
    int n;
    void init(int n_) {
        n = n_;
        bit.resize(n);
    }
    void init(std::vector<T>& a) {
        n = (int) a.size();
        a.assign(n, 0);
        for (int i = 0; i < (int) a.size(); i++) {
            add(i, a[i]);
        }
    }
    T sum(int r) {
        T ret = 0;
        for (; r >= 0; r = (r & (r + 1)) - 1) ret += bit[r];
        return ret;
    }
    T query(int l, int r) {
        return sum(r) - sum(l - 1);
    }
    void add(int idx, T delta) {
        for (; idx < n; idx = idx | (idx + 1)) bit[idx] += delta;
    }
};

int main() {
    cin.tie(0)->sync_with_stdio(0);
    string s; cin >> s;
    int n = sz(s);
    SuffixArray S; S.init(s);
    vector<int> m = manacher(s);
    long long ans = 0;
    for (ll x : m) 
        ans = max(ans, x);
    {
        vector<int> pal(n);
        for (int i = 1; i < n; i++) {
            pal[i] = m[2 * i - 1] / 2;
        }
        IntervalJoin I; I.init(n);
        vector<vector<int>> bucket(n);
        vector<vector<int>> gap(n);
        for (int i = 0; i < n; i++) {
            bucket[pal[i]].push_back(i);
        }
        for (int i = 0; i < n - 1; i++) {
            int i1 = S.sa[i + 1];
            int i2 = S.sa[i + 2];
            int val = S.get_lcp(i1, i2);
            gap[val].push_back(i);
        }
        BIT<long long> bit;
        bit.init(n);
        for (int i = n - 1; i >= 0; i--) {
            for (int x : bucket[i]) {
                bit.add(S.isa[x] - 1, 1); // add 1 to a potential location
            }
            for (int x : gap[i]) {
                I.unite(x, x + 1);
            }
            for (int x : bucket[i]) {
                int y = S.isa[x]-1;
                pi p = I.get_interval(y);
                int res = bit.query(p.first, p.second);
                ans = max(ans, 1LL * 2 * i * res);
            }
        }
    }
    {
        vector<int> pal(n);
        for (int i = 0; i < n; i++) {
            pal[i] = m[2 * i] / 2;
        }
        vector<vector<int>> bucket(n);
        vector<vector<int>> gap(n);
        for (int i = 0; i < n; i++) {
            bucket[pal[i]].push_back(i);
        }
        for (int i = 0; i < n - 1; i++) {
            int i1 = S.sa[i + 1];
            int i2 = S.sa[i + 2];
            int val = S.get_lcp(i1, i2);
            if (val)
                gap[val - 1].push_back(i);
        }
        IntervalJoin I; I.init(n);
        BIT<long long> bit;
        bit.init(n);
        for (int i = n - 1; i >= 0; i--) {
            for (int x : bucket[i]) {
                bit.add(S.isa[x] - 1, 1); 
            }
            for (int x : gap[i]) {
                I.unite(x, x + 1);
            }
            for (int x : bucket[i]) {
                int y = S.isa[x]-1;
                pi p = I.get_interval(y);
                int res = bit.query(p.first, p.second);
                ans = max(ans, 1LL * (2 * i + 1) * res);
            }
        }
;
    }
    cout << ans << '\n';
    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 364 KB Output is correct
2 Correct 1 ms 380 KB Output is correct
3 Correct 0 ms 364 KB Output is correct
4 Correct 1 ms 364 KB Output is correct
5 Correct 1 ms 364 KB Output is correct
6 Correct 1 ms 384 KB Output is correct
7 Correct 1 ms 384 KB Output is correct
8 Correct 1 ms 364 KB Output is correct
9 Correct 0 ms 364 KB Output is correct
10 Correct 1 ms 364 KB Output is correct
11 Correct 1 ms 364 KB Output is correct
12 Correct 1 ms 364 KB Output is correct
13 Correct 1 ms 364 KB Output is correct
14 Correct 1 ms 364 KB Output is correct
15 Correct 1 ms 364 KB Output is correct
16 Correct 0 ms 364 KB Output is correct
17 Correct 1 ms 364 KB Output is correct
18 Correct 1 ms 364 KB Output is correct
19 Correct 1 ms 364 KB Output is correct
20 Correct 1 ms 364 KB Output is correct
21 Correct 1 ms 364 KB Output is correct
22 Correct 1 ms 364 KB Output is correct
23 Correct 1 ms 364 KB Output is correct
24 Correct 1 ms 364 KB Output is correct
25 Correct 1 ms 364 KB Output is correct
26 Correct 1 ms 364 KB Output is correct
27 Correct 1 ms 364 KB Output is correct
28 Correct 1 ms 384 KB Output is correct
29 Correct 1 ms 364 KB Output is correct
30 Correct 1 ms 364 KB Output is correct
31 Correct 1 ms 364 KB Output is correct
32 Correct 1 ms 364 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 492 KB Output is correct
2 Correct 1 ms 492 KB Output is correct
3 Correct 1 ms 492 KB Output is correct
4 Correct 1 ms 492 KB Output is correct
5 Correct 1 ms 492 KB Output is correct
6 Correct 1 ms 492 KB Output is correct
7 Correct 1 ms 512 KB Output is correct
8 Correct 1 ms 492 KB Output is correct
9 Correct 1 ms 492 KB Output is correct
10 Correct 1 ms 492 KB Output is correct
11 Correct 1 ms 492 KB Output is correct
12 Correct 1 ms 492 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 2196 KB Output is correct
2 Correct 8 ms 2068 KB Output is correct
3 Correct 8 ms 2284 KB Output is correct
4 Correct 8 ms 2196 KB Output is correct
5 Correct 8 ms 2068 KB Output is correct
6 Correct 7 ms 1940 KB Output is correct
7 Correct 7 ms 2088 KB Output is correct
8 Correct 8 ms 1940 KB Output is correct
9 Correct 8 ms 1940 KB Output is correct
10 Correct 8 ms 2068 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 85 ms 20760 KB Output is correct
2 Correct 83 ms 18712 KB Output is correct
3 Correct 88 ms 20768 KB Output is correct
4 Correct 86 ms 19220 KB Output is correct
5 Correct 108 ms 17864 KB Output is correct
6 Correct 104 ms 18200 KB Output is correct
7 Correct 90 ms 18080 KB Output is correct
8 Correct 118 ms 17380 KB Output is correct
9 Correct 102 ms 18092 KB Output is correct
10 Correct 110 ms 18200 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 284 ms 63480 KB Output is correct
2 Correct 280 ms 54808 KB Output is correct
3 Correct 298 ms 63788 KB Output is correct
4 Correct 286 ms 56336 KB Output is correct
5 Correct 458 ms 55892 KB Output is correct
6 Correct 310 ms 55696 KB Output is correct
7 Correct 320 ms 54672 KB Output is correct
8 Correct 518 ms 53724 KB Output is correct
9 Correct 492 ms 53412 KB Output is correct
10 Correct 436 ms 56164 KB Output is correct
11 Correct 281 ms 61304 KB Output is correct
12 Correct 476 ms 54112 KB Output is correct