Codeforces Round #778 (Div. 1 + Div. 2)
阿新 • • 發佈:2022-03-21
F. Minimal String Xoration
題目描述
解法
記 \(f(s,d)\) 為 \(t_i=s_{i\oplus d}\) 的字串 \(t\),可以將問題轉化成:把 \(f(s,0),f(s,1)...f(s,2^n-1)\) 按照字典序從小到大排序,那麼字典序最小的就是答案。
那麼可以考慮類似字尾陣列一樣倍增,假設現在我們知道在 \(2^k\) 的字首意義下,\(f(s,0\sim2^{n}-1)\) 的大小關係,我們考慮快速計算在 \(2^{k+1}\) 的字首意義下 \(f(s,0\sim 2^{n}-1)\) 的大小關係。
設 \(rk[i]\) 表示 \(f(s,i)\)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int M = 1<<18; int read() { int x=0,f=1;char c; while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;} while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } int n,b[26],rk[M],sa[M],nw[M];char s[M]; signed main() { n=1<<read();scanf("%s",s); for(int i=0;i<n;i++) b[s[i]-'a']++; for(int i=1;i<26;i++) b[i]+=b[i-1]; for(int i=0;i<n;i++) rk[i]=b[s[i]-'a']; for(int w=1;w<n;w<<=1) { for(int i=0;i<n;i++) sa[i]=i; sort(sa,sa+n,[&](int i,int j) {return rk[i]==rk[j]?rk[i^w]<rk[j^w]:rk[i]<rk[j];}); nw[sa[0]]=1;int num=1; for(int i=1;i<n;i++) nw[sa[i]]=(rk[sa[i]]==rk[sa[i-1]] && rk[sa[i]^w]==rk[sa[i-1]^w])?num:++num; memcpy(rk,nw,sizeof rk); } for(int i=0;i<n;i++) printf("%c",s[i^sa[0]]); puts(""); }