Submission #1067564

#TimeUsernameProblemLanguageResultExecution timeMemory
1067564gs25Palindromes (APIO14_palindrome)C++17
100 / 100
189 ms36588 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 = 600100; 
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 v[MAXN*4] = {};
  void build(int node, int s, int e){
    if(s==e) {
      v[node] = a[s]; return; 
    }
    int m = s+e>>1; 
    build(2*node,s,m); build(node*2+1,m+1,e); 
    v[node] = max(v[node*2],v[node*2+1]); 
  }
  int query(int node, int s, int e, int l, int r, int k){
    // a[x]>=k 인 최대의 x 
    //dbg(node,s,e,l,r,v[node],k)
    if(v[node]<k) return -1; 
    int m = s+e>>1; 
    if(r<s||l>e) return -1; 
    if(s==e) return s; 
    int rr = query(2*node+1,m+1,e,l,r,k); 
    if(rr!=-1) return rr; 
    return query(2*node,s,m,l,r,k); 
  }
  int query(int i, int j){
    int xx = query(1,0,n*2-1,2*i,i+j,-2*i); 
    return xx-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; 
    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) return; 
  int pos = rmq_idx.query(s,e-1);
  int st = sfx[pos], len = lcp[pos]; 
  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.push_back(s[i]); 
    ss.push_back('#');
  }
  manacher(ss); 
  rmq_idx.build(); 
  shit.build(1,0,n*2-1); 

  dnc(0,n-1); 
  for(int i=0; i<n*2-1; i++){
    int ddd = i+a[i]; 
    if(i%2==0) ans = max(ans,(ll)(ddd/2)*2 + 1); 
    else ans = max(ans,(ll)((ddd+1)/2)*2);
  }
  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 'void shit_::build(int, int, int)':
palindrome.cpp:78:14: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   78 |     int m = s+e>>1;
      |             ~^~
palindrome.cpp: In member function 'int shit_::query(int, int, int, int, int, int)':
palindrome.cpp:86:14: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   86 |     int m = s+e>>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...