题解 [CF1654F] Minimal String Xoration
后缀数组(倍增排序?)还能这么玩,长见识了
发现这个异或是作用在下标上的,所以基本上没什么可以用的贪心策略
那么直接说正解:
令 \(f(s, x)=s_{i\oplus x}\)
那么若已知所有的 \(x\) 以 \(f(s, x)\) 的 \([0:2^{k-1}-1]\) 为关键字的排序结果,可以推出以 \([0:2^k-1]\) 为关键字的排序结果
具体地,考虑 \(f(s, x)[2^{k-1}:2^k-1]=f(s, x\oplus 2^{k-1})[0, 2^{k-1}-1]\) 就可以了
那么复杂度是 \(O(n2^n)\) 的
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 300010
#define ll long long
//#define int long long
int n, m=256;
char s[N];
int cnt[N], sa[N], rk[N], oldrk[N<<1], id[N], px[N];
inline bool cmp(int a, int b, int w) {return oldrk[a]==oldrk[b]&&oldrk[a^w]==oldrk[b^w];}
signed main()
{
scanf("%d%s", &n, s);
n=1<<n;
for (int i=0; i<n; ++i) ++cnt[rk[i]=s[i]];
for (int i=1; i<=m; ++i) cnt[i]+=cnt[i-1];
for (int i=0; i<n; ++i) sa[--cnt[rk[i]]]=i;
for (int w=1,p; w<n; w<<=1,m=p) {
p=0;
for (int i=0; i<n; ++i) id[p++]=sa[i]^w;
for (int i=0; i<=m; ++i) cnt[i]=0;
for (int i=0; i<n; ++i) ++cnt[px[i]=rk[id[i]]];
for (int i=1; i<=m; ++i) cnt[i]+=cnt[i-1];
for (int i=n-1; ~i; --i) sa[--cnt[px[i]]]=id[i];
for (int i=0; i<n; ++i) oldrk[i]=rk[i];
rk[sa[0]]=p=1;
for (int i=1; i<n; ++i) rk[sa[i]]=cmp(sa[i], sa[i-1], w)?p:++p;
if (p==n) break;
}
int x=sa[0];
for (int i=0; i<n; ++i) printf("%c", s[i^x]);
printf("\n");
return 0;
}