Submission #1067508

#TimeUsernameProblemLanguageResultExecution timeMemory
1067508gs25Palindromes (APIO14_palindrome)C++17
47 / 100
1094 ms19548 KiB
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,avx,avx2")
#include <bits/stdc++.h>
#define pb push_back
#define all(v) (v).begin(), (v).end()
#define rep(i, n) for (int i = 0; i < n; ++i)
#define rrep(i, n) for (int i = 1; i <= n; ++i)
#define ff first
#define ss second
using namespace std;
typedef long long ll;

void __print(int x) { cerr << x; }
void __print(long x) { cerr << x; }
void __print(long long x) { cerr << x; }
void __print(unsigned x) { cerr << x; }
void __print(unsigned long x) { cerr << x; }
void __print(unsigned long long x) { cerr << x; }
void __print(float x) { cerr << x; }
void __print(double x) { cerr << x; }
void __print(long double x) { cerr << x; }
void __print(char x) { cerr << '\'' << x << '\''; }
void __print(const char *x) { cerr << '\"' << x << '\"'; }
void __print(const string &x) { cerr << '\"' << x << '\"'; }
void __print(bool x) { cerr << (x ? "true" : "false"); }

template <typename T, typename V> void __print(const pair<T, V> &x) {
  cerr << '{';
  __print(x.first);
  cerr << ", ";
  __print(x.second);
  cerr << '}';
}
template <typename T> void __print(const T &x) {
  int f = 0;
  cerr << '{';
  for (auto &i : x)
    cerr << (f++ ? ", " : ""), __print(i);
  cerr << "}";
}
void _print() { cerr << "]\n"; }
template <typename T, typename... V> void _print(T t, V... v) {
  __print(t);
  if (sizeof...(v))
    cerr << ", ";
  _print(v...);
}
#ifdef LOCAL
#define dbg(x...)                                                              \
  cerr << "\e[91m" << __func__ << ":" << __LINE__ << " [" << #x << "] = [";    \
  _print(x);                                                                   \
  cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif

const int MAXN = 300100; 
int a[MAXN*2]; 
int lcp[MAXN],sfx[MAXN],ord[MAXN],nord[MAXN],p,n,rev[MAXN];
string s; 

void manacher(string s){
  int k=-1,r=-1; 
  int n = s.size(); 
  for(int i=0; i<n; i++){
    if(i<r) a[i] = min(a[2*k-i],r-i); 
    while(i-a[i]-1>=0 && i+a[i]+1<n && s[i-a[i]-1]==s[i+a[i]+1]) a[i]++; 
    if(i+a[i]>r) r=i+a[i],k=i;
  }
  rep(i,n) a[i] = a[i]-i; 
}

struct shit_{
  int sz = 1<<20; int tree[1<<21] = {}; 
  void build(){
    int nn = n*2; 
    for(int i=sz; i<sz*2; i++){
      if(i-sz<nn) tree[i] = a[i-sz]; 
      else tree[i] = -10000000; 
    }
    for(int i=sz-1; i>0; i--) tree[i] = max(tree[i<<1],tree[(i<<1)|1]); 
  }
  int Max(int l, int r){
    l = l+sz, r = r+sz; 
    int re = -10000000; 
    while(l<=r){
      if(l&1) re = max(re,tree[l++]); 
      if(~r&1) re = max(re,tree[r--]); 
      r>>=1; l>>=1; 
    }
    return re; 
  }
  int query(int i, int j){
    if(j<i) return 0; 
    int l = 2*i,r=i+j; 
    int re = -1; 
    while(l<=r){
      int m = l+r>>1; 
      if(Max(m,r)>=-2*i) re=m,l=m+1; 
      else r=m-1; 
    }
    dbg(i,j,re)
    assert(re>=2*i && re<=i+j); 
    return re-i*2+1; 
  }
}shit; 

bool cmp(int i, int j){
  if(ord[i]!=ord[j]) return ord[i] < ord[j]; 
  i += p; j+= p; 
  return (i<n && j<n) ? ord[i] < ord[j] : i>j; 
}

int cnt[MAXN]; 

void fuck(){
  rep(i,n) ord[i] = s[i], sfx[i] = i; 
  p = 1; int pcnt=0; 
  while(1){
    memset(cnt,0,sizeof(cnt)); 
    for(int i=0; i<n; i++) cnt[ord[min(i+p,n)]]++;
    for(int i=1; i<=n || i<256; i++) cnt[i] += cnt[i-1]; 
    for(int i=0; i<n; i++) nord[--cnt[ord[min(i+p,n)]]] = i;
    memset(cnt,0,sizeof(cnt)); 
    for(int i=0; i<n; i++) cnt[ord[i]]++; 
    for(int i=1; i<=n || i<256; i++) cnt[i] += cnt[i-1]; 
    for(int i=n-1; i>=0; i--) sfx[--cnt[ord[nord[i]]]] = nord[i]; 
    if(pcnt==n-1) break; 
    memset(nord,0,sizeof(nord)); 
    nord[sfx[0]] = 0; 
    for(int i=1; i<n; i++) nord[sfx[i]] = nord[sfx[i-1]] + cmp(sfx[i-1],sfx[i]); 
    pcnt = nord[sfx[n-1]]; 
    memcpy(ord,nord,sizeof(ord)); 
    p*=2; 
  }
  rep(i,n) rev[sfx[i]] = i; 
  for(int i=0,h=0; i<n; i++){
    if(rev[i]!=n-1){
      int nx = sfx[rev[i]+1]; 
      while(nx+h<n && i+h<n && s[nx+h]==s[i+h]) h++; 
      lcp[rev[i]] = h; 
    }
    h = max(h-1,0); 
  }
}

struct rmq_idx_ {
  int sz = 1<<19; int tree[1<<20] = {};  
  void build(){
    for(int i=sz; i<sz*2; i++) tree[i] = i-sz;
    for(int i=sz-1; i>0; i--){
      int ll = tree[i<<1], rr = tree[(i<<1)|1]; 
      if(rr>=MAXN || ll>=MAXN) tree[i] = MAXN; 
      else {
        tree[i] = (lcp[ll] < lcp[rr] ? ll : rr);  
      } 
    }
  }
  int query(int l, int r){
    l = l+sz, r = r+sz; 
    int M = MAXN+100, ans=-1; 
    while(l<=r){
      if(l&1){
        if(lcp[tree[l]]<M) ans = tree[l], M = lcp[tree[l]]; 
        l++; 
      }
      if(~r&1){
        if(lcp[tree[r]]<M) ans=tree[r], M = lcp[tree[r]]; 
        r--; 
      }
      l>>=1; r>>=1; 
    }
    return ans; 
  }
}rmq_idx;

ll ans = 0; 
void dnc(int s, int e){
  if(s==e){
    int pos = sfx[s]; 
    ans = max(ans, (ll)shit.query(pos,n-1)); return; 
  }
  int pos = rmq_idx.query(s,e-1);
  int st = sfx[pos], len = lcp[pos]; 
  dbg(s,e,pos,st,len)
  ans = max(ans,(ll)(e-s+1)*shit.query(st,st+len-1));
  dnc(s,pos);
  dnc(pos+1,e);  
}

void solve(){
  cin >> s; n = s.size(); 
  fuck(); 
  string ss; 
  rep(i,n){
    ss = ss + s[i]; ss += '#'; 
    dbg(i,sfx[i],lcp[i])
  }
  manacher(ss); 
  rmq_idx.build(); 
  shit.build(); 
  dnc(0,n-1); 
  cout << ans; 
};


int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  int t = 1;
  // cin >> t;
  while(t--) solve(); 
  return 0;
}

Compilation message (stderr)

palindrome.cpp: In member function 'int shit_::query(int, int)':
palindrome.cpp:97:16: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   97 |       int m = l+r>>1;
      |               ~^~
#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...