답안 #23275

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
23275 2017-05-05T17:47:40 Z Nurlykhan 회문 (APIO14_palindrome) C++11
100 / 100
983 ms 35860 KB
#include <bits/stdc++.h>

#define pii pair<int, int>
#define f first
#define s second
#define pb push_back
#define mp make_pair
#define ll long long 
#define ld long double
#define sz(v) int(v.size())
#define all(v) v.begin(), v.end()

using namespace std;

const int N = (int) 5e5 + 10;
const int M = (int) 2e6 + 10;
const ll LINF = (ll) 1e18;
const int mod1 = (int) 1e9 + 7;
const int mod2 = (int) 1e7 + 7;
const double EPS = (double) 1e-9;
string st;
ll ans;
int n;
pii h[N], h1[N];
pii p[N];

int ncol[N], col[N], suff[N], head[N], nsuff[N], pos[N];

bool cmp1(int x, int y) {
   return st[x] < st[y];
}

void suffix_array() {
   for(int i = 0; i < n; i++) suff[i] = i;
   sort(suff, suff + n, cmp1);
   int cn = 0;
   for(int i = 0; i < n; i++) {
      if(!i || st[suff[i]] != st[suff[i - 1]]) {
         col[suff[i]] = cn++;
         head[cn - 1] = i;
      }
      else col[suff[i]] = cn - 1;
   }
   for(int i = 1; i < n; i += i) {
      for(int j = 0; j < n; j++) {
         int k = suff[j] - i;
         if(k < 0) k += n;
         nsuff[head[col[k]]++] = k;
      }
      cn = 0;
      for(int j = 0; j < n; j++)
         suff[j] = nsuff[j];
      for(int j = 0; j < n; j++) {
         if(!j || col[suff[j]] != col[suff[j - 1]] || col[(suff[j] + i) % n] != col[(suff[j - 1] + i) % n])
            ncol[suff[j]] = cn++, head[cn - 1] = j;
         else ncol[suff[j]] = cn - 1;
      }
      for(int j = 0; j < n; j++) col[j] = ncol[j];
   }
   for(int j = 0; j < n; j++) {
      pos[suff[j]] = j;
   }
}

inline pii get_hash(const int &l, const int &r) {
    pii ans = {(h[r].f - (l ? h[l - 1].f : 0) + mod1), (h[r].s - (l ? h[l - 1].s : 0) + mod2)};
    if (ans.f >= mod1) ans.f -= mod1;
    if (ans.s >= mod2) ans.s -= mod2;
    ans.f = ans.f * 1ll * p[sz(st) - 1 - r].f % mod1;
    ans.s = ans.s * 1ll * p[sz(st) - 1 - r].s % mod2;
    return ans;
}

inline pii get_revhash(const int &l, const int &r) {
    pii ans = {(h1[l].f - h1[r + 1].f + mod1), (h1[l].s - h1[r + 1].s + mod2)};
    if (ans.f >= mod1) ans.f -= mod1;
    if (ans.s >= mod2) ans.s -= mod2;
    ans.f = ans.f * 1ll * p[l].f % mod1;
    ans.s = ans.s * 1ll * p[l].s % mod2;
    return ans;
}

inline int first_diff(const pii &x, const pii &y) {
    int l = 0, r = min(x.s - x.f, y.s - y.f);
    int neq = -1;
    while (l <= r) {
       
        int m = (l + r) / 2;
        if (get_hash(x.f, x.f + m) == get_hash(y.f, y.f + m)) {
            l = m + 1;
        } else {
            neq = m;
            r = m - 1;
        }
    }
    return neq;
}

bool cmp(pii x, pii y) {
    int m = min(x.s - x.f, y.s - y.f);
    if (get_hash(x.f, x.f + m) == get_hash(y.f, y.f + m)) 
        return x.s - x.f < y.s - y.f;
    return pos[x.f] < pos[y.f];
}

vector<int> get_shit1(vector<int> v) {
    vector<int> st, ret(sz(v));
    for (int i = 0; i < sz(v); i++) {
        while (!st.empty() && v[i] <= v[st.back()]) st.pop_back();
        ret[i] = st.empty() ? 0 : st.back() + 1;
        st.pb(i);
    }
    return ret;
}

vector<int> get_shit2(vector<int> v) {
    vector<int> st, ret(sz(v));
    for (int i = sz(v) - 1; i >= 0; i--) {
        while (!st.empty() && v[i] <= v[st.back()]) st.pop_back();
        ret[i] = st.empty() ? sz(v) - 1 : st.back() - 1;
        st.pb(i);
    }
    return ret;
}

void solve_odd() {
    vector<pii> v;
    for (int i = 0; i < sz(st); i++) {
        int l = 0, r = sz(st);
        int j = 0;
        while (l <= r) {
            int m = (l + r) / 2;
            if (i - m >= 0 && i + m < sz(st) && get_hash(i, i + m) == get_revhash(i - m, i)) {
                l = m + 1;
                j = m;
            } else {
                r = m - 1;
            }
        }
        v.pb(mp(i, i + j));
    }
    sort(all(v), cmp);
    //for (auto it : v) cout << it << endl; cout << "-----\n";
    vector<int> lcp(sz(v) - 1);
    for (int i = 0; i + 1 < sz(v); i++) {
        lcp[i] = first_diff(v[i], v[i + 1]);
        if (lcp[i] == -1) 
            lcp[i] = min(v[i].s - v[i].f, v[i + 1].s - v[i + 1].f) + 1;
    }
    for (int i = 0; i < sz(v); i++) {
        ans = max(ans, 2ll * (v[i].s - v[i].f + 1) - 1);
    }
    vector<int> tmp1 = get_shit1(lcp);
    vector<int> tmp2 = get_shit2(lcp);
    for (int i = 0; i < sz(lcp); i++) {
        int occurs = tmp2[i] - tmp1[i] + 2;
        ans = max(ans, occurs * 1ll * (lcp[i] * 2 - 1));
    }
}


void solve_even() {
    vector<pii> v;
    for (int i = 0; i < sz(st); i++) {
        int l = 0, r = sz(st);
        int j = -1;
        while (l <= r) {
            int m = (l + r) / 2;
            if (i - 1 - m >= 0 && i + m < sz(st) && get_hash(i, i + m) == get_revhash(i - 1 - m, i - 1)) {
                l = m + 1;
                j = m;
            } else {
                r = m - 1;
            }
        }
        if (j != -1) 
            v.pb(mp(i, i + j));
    }
    if (v.empty()) 
        return;
    sort(all(v), cmp);
    vector<int> lcp(sz(v) - 1);
    //for (auto it : v) cout << it << endl; cout << "-----\n";
    for (int i = 0; i + 1 < sz(v); i++) {
        lcp[i] = first_diff(v[i], v[i + 1]);
        if (lcp[i] == -1) 
            lcp[i] = min(v[i].s - v[i].f, v[i + 1].s - v[i + 1].f) + 1;
    }
    for (int i = 0; i < sz(v); i++) {
        ans = max(ans, 2ll * (v[i].s - v[i].f + 1));
    }
    vector<int> tmp1 = get_shit1(lcp);
    vector<int> tmp2 = get_shit2(lcp);
    for (int i = 0; i < sz(lcp); i++) {
        int occurs = tmp2[i] - tmp1[i] + 2;
        ans = max(ans, occurs * 2ll * lcp[i]);
    }
}

int main() {
    #define fn "balls"
    #ifdef witch
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #else
//        freopen(fn".in", "r", stdin);
//        freopen(fn".out", "w", stdout);
    #endif
    cin >> st;
    st = st + "#";
    n = sz(st);
    assert(n < N);
    p[0] = {1, 1};
    for (int i = 1; i < n; i++) {
        p[i].f = p[i - 1].f * 37LL % mod1;
        p[i].s = p[i - 1].s * 37LL % mod2;
    }
    for (int i = 0; i < n; i++) {
        if (i) {
            h[i] = h[i - 1];
        }
        h[i].f = (h[i].f + (st[i] + 1) * 1LL * p[i].f) % mod1;
        h[i].s = (h[i].s + (st[i] + 1) * 1LL * p[i].s) % mod2;
    }
    for (int i = n - 1; i >= 0; i--) {
        h1[i].f = (h1[i + 1].f + (st[i] + 1) * 1ll * p[n - 1 - i].f) % mod1;
        h1[i].s = (h1[i + 1].s + (st[i] + 1) * 1ll * p[n - 1 - i].s) % mod2;
    }
    suffix_array();
    solve_odd();
    solve_even();
    cout << ans;
    return 0;
}
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 25468 KB Output is correct
2 Correct 0 ms 25468 KB Output is correct
3 Correct 0 ms 25468 KB Output is correct
4 Correct 0 ms 25468 KB Output is correct
5 Correct 0 ms 25468 KB Output is correct
6 Correct 0 ms 25468 KB Output is correct
7 Correct 0 ms 25468 KB Output is correct
8 Correct 0 ms 25468 KB Output is correct
9 Correct 0 ms 25468 KB Output is correct
10 Correct 0 ms 25468 KB Output is correct
11 Correct 0 ms 25468 KB Output is correct
12 Correct 0 ms 25468 KB Output is correct
13 Correct 0 ms 25468 KB Output is correct
14 Correct 0 ms 25468 KB Output is correct
15 Correct 0 ms 25468 KB Output is correct
16 Correct 0 ms 25468 KB Output is correct
17 Correct 0 ms 25468 KB Output is correct
18 Correct 0 ms 25468 KB Output is correct
19 Correct 0 ms 25468 KB Output is correct
20 Correct 0 ms 25468 KB Output is correct
21 Correct 0 ms 25468 KB Output is correct
22 Correct 0 ms 25468 KB Output is correct
23 Correct 0 ms 25468 KB Output is correct
24 Correct 0 ms 25468 KB Output is correct
25 Correct 0 ms 25468 KB Output is correct
26 Correct 0 ms 25468 KB Output is correct
27 Correct 0 ms 25468 KB Output is correct
28 Correct 0 ms 25468 KB Output is correct
29 Correct 0 ms 25468 KB Output is correct
30 Correct 0 ms 25468 KB Output is correct
31 Correct 0 ms 25468 KB Output is correct
32 Correct 0 ms 25468 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 25468 KB Output is correct
2 Correct 0 ms 25468 KB Output is correct
3 Correct 0 ms 25468 KB Output is correct
4 Correct 0 ms 25468 KB Output is correct
5 Correct 0 ms 25468 KB Output is correct
6 Correct 0 ms 25468 KB Output is correct
7 Correct 0 ms 25468 KB Output is correct
8 Correct 0 ms 25468 KB Output is correct
9 Correct 0 ms 25468 KB Output is correct
10 Correct 0 ms 25468 KB Output is correct
11 Correct 0 ms 25468 KB Output is correct
12 Correct 0 ms 25468 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 9 ms 25860 KB Output is correct
2 Correct 9 ms 25884 KB Output is correct
3 Correct 19 ms 25860 KB Output is correct
4 Correct 23 ms 25860 KB Output is correct
5 Correct 9 ms 25884 KB Output is correct
6 Correct 9 ms 25884 KB Output is correct
7 Correct 9 ms 25884 KB Output is correct
8 Correct 9 ms 25880 KB Output is correct
9 Correct 9 ms 25884 KB Output is correct
10 Correct 9 ms 25884 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 149 ms 28452 KB Output is correct
2 Correct 136 ms 28332 KB Output is correct
3 Correct 289 ms 28564 KB Output is correct
4 Correct 273 ms 28568 KB Output is correct
5 Correct 126 ms 28332 KB Output is correct
6 Correct 126 ms 28332 KB Output is correct
7 Correct 173 ms 28332 KB Output is correct
8 Correct 166 ms 28332 KB Output is correct
9 Correct 179 ms 28332 KB Output is correct
10 Correct 133 ms 28332 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 456 ms 34920 KB Output is correct
2 Correct 486 ms 34920 KB Output is correct
3 Correct 983 ms 35860 KB Output is correct
4 Correct 846 ms 35496 KB Output is correct
5 Correct 429 ms 34920 KB Output is correct
6 Correct 526 ms 34920 KB Output is correct
7 Correct 596 ms 34920 KB Output is correct
8 Correct 576 ms 34920 KB Output is correct
9 Correct 556 ms 34920 KB Output is correct
10 Correct 469 ms 34920 KB Output is correct
11 Correct 379 ms 34920 KB Output is correct
12 Correct 583 ms 34920 KB Output is correct