제출 #1118475

#제출 시각아이디문제언어결과실행 시간메모리
1118475VinhLuu회문 (APIO14_palindrome)C++17
100 / 100
880 ms48296 KiB
#include <bits/stdc++.h>
//#define int long long
#define ll long long
#define fi first
#define se second
#define pb push_back
#define all(lmao) lmao.begin(), lmao.end()

using namespace std;

typedef pair<ll, ll> pii;

const int N = 3e5 + 5;
const int M = 1e6 + 5;
const ll oo = 1e16;

int n, a[N];

int pos[N], sa[N], gap, tmp[N], lcp[N], LG[N], dp[22][N];
ll ans = 0;

bool cmp(int x,int y){
  if(pos[x] != pos[y]) return pos[x] < pos[y];
  x += gap;
  y += gap;
  return (x <= n && y <= n ? pos[x] < pos[y] : x > y);
}

void SA(){
  gap = 1;
  for(int i = 1; i <= n; i ++) pos[i] = a[i], sa[i] = i;
  while(true){
    sort(sa + 1, sa + n + 1, cmp);
    for(int i = 2; i <= n; i ++) tmp[i] = tmp[i - 1] + cmp(sa[i - 1], sa[i]);
    for(int i = 1; i <= n; i ++) pos[sa[i]] = tmp[i] + 1;
    if(tmp[n] == n - 1) break;
    gap = gap * 2;
  }


  for(int i = 1, k = 0; i <= n; i ++){
    if(pos[i] == n) continue;
    for(int j = sa[pos[i] + 1]; a[i + k] == a[j + k]; ) k ++;
    lcp[pos[i]] = k;
    if(k) k--;
  }

  for(int i = 1; i <= n; i ++) LG[i] = (i == 1 ? 0 : LG[i / 2] + 1);
  for(int i = n; i >= 1; i --){
    dp[0][i] = lcp[i];
    for(int j = 1; j <= 20 && i + (1 << j) - 1 <= n; j ++){
      dp[j][i] = min(dp[j - 1][i], dp[j - 1][i + (1 << (j - 1))]);
    }
  }
}

int kq[2][N];

namespace Hash{
  #define int long long
  mt19937 rd(2615367263);
  int ra(int l,int r){
    return l + rd() % (r - l + 1);
  }

  const int MOD[2] = {ra(1e9, 2e9), (int)1e9 + 7};
  const int base = 137;

  int pw[2][N], h[2][N], g[2][N];

  int get(int l,int r){
    int A = (h[0][r] + MOD[0] - h[0][l - 1] * pw[0][r - l + 1] % MOD[0]) % MOD[0];
    int B = (h[1][r] + MOD[1] - h[1][l - 1] * pw[1][r - l + 1] % MOD[1]) % MOD[1];
    return A * MOD[1] + B;
  }

  int rev(int l,int r){
    int A = (g[0][l] + MOD[0] - g[0][r + 1] * pw[0][r - l + 1] % MOD[0]) % MOD[0];
    int B = (g[1][l] + MOD[1] - g[1][r + 1] * pw[1][r - l + 1] % MOD[1]) % MOD[1];
    return A * MOD[1] + B;
  }

  void solve(){
    pw[0][0] = pw[1][0] = 1;
    for(int i = 1; i <= n; i ++) for(int j = 0; j <= 1; j ++){
      pw[j][i] = pw[j][i - 1] * base % MOD[j];
      h[j][i] = (h[j][i - 1] * base % MOD[j] + a[i]) % MOD[j];
    }

    for(int i = n; i >= 1; i --) for(int j = 0; j <= 1; j ++) {
      g[j][i] = (g[j][i + 1] * base % MOD[j] + a[i]) % MOD[j];
    }

    for(int i = 1; i <= n; i ++){
      int l = 1, r = min(n - i, i);
      while(l <= r) {
        int mid = (l + r) / 2;
        if(get(i - mid + 1, i) == rev(i + 1, i + mid)){
          kq[0][i] = mid;
          l = mid + 1;
        }else r = mid - 1;
      }

      l = 1, r = min(n - i + 1, i);
      while(l <= r) {
        int mid = (l + r) / 2;
//        if(i == 4) {
//          cerr << i - mid + 1 << " " << i << " " << get(i - mid + 1, i) << " h\n";
//          cerr << i << " " << i + mid - 1
//        }
        if(get(i - mid + 1, i) == rev(i, i + mid - 1)){
          kq[1][i] = mid;
          l = mid + 1;
        }else r = mid - 1;
      }
    }
  }
}

int query(int l,int r){
  int k = LG[r - l + 1];
  return min(dp[k][l], dp[k][r - (1 << k) + 1]);
}

int bs(int x, int len){
  int i = pos[x];
  int l = 1, r = i - 1, _left = i;
  while(l <= r){
    int mid = (l + r) / 2;
    if(query(mid, i - 1) >= len){
      _left = mid;
      r = mid - 1;
    }else l = mid + 1;
  }
  l = i, r = n - 1;
  int _right = i;
  while(l <= r) {
    int mid = (l + r) / 2;
    if(query(i, mid) >= len){
      _right = mid + 1;
      l = mid + 1;
    }else r = mid - 1;
  }
  return _right - _left + 1;
}


signed main(){
  ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);

  #define task "v"
  if(fopen(task ".inp","r")){
    freopen(task ".inp","r",stdin);
    freopen(task ".out","w",stdout);
  }

  string s; cin >> s;
  n = s.size(); s = " " + s;
  for(int i = 1; i <= n; i ++) a[i] = (int)(s[i] - 'a') + 1;

  SA();

  Hash :: solve();

  for(int i = 1; i <= n; i ++){
    if(kq[0][i]){
      int tmp = bs(i - kq[0][i] + 1, 2 * kq[0][i]);
      ans = max(ans, 1ll * tmp * 2 * kq[0][i]);
    }
    if(kq[1][i]){
      int tmp = bs(i - kq[1][i] + 1, 2 * kq[1][i] - 1);
      ans = max(ans, 1ll * tmp * (2 * kq[1][i] - 1));
    }
  }
  cout << ans;
}

컴파일 시 표준 에러 (stderr) 메시지

palindrome.cpp: In function 'int main()':
palindrome.cpp:153:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  153 |     freopen(task ".inp","r",stdin);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
palindrome.cpp:154:12: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  154 |     freopen(task ".out","w",stdout);
      |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...