其他分享
首页 > 其他分享> > #基数排序#CF1654F Minimal String Xoration

#基数排序#CF1654F Minimal String Xoration

作者:互联网

题目传送门


分析

有没有一种办法可以将每个 \(j\) 的比较过程同时进行,

可以发现其实这个过程很像后缀排序,实际上只是加号变成了异或,

从低位到高位重新将字符串排名,用同样的方法做到 \(O(2^nn)\)


代码

#include <iostream>
using namespace std;
const int N=300011; string S;
int n,two[N],rk[N],tp[N],Rk[N],M,c[N];
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>S,two[0]=1;
	for (int i=1;i<=n;++i) two[i]=two[i-1]<<1;
	for (int i=0;i<two[n];++i) rk[i]=i,tp[i]=S[i]-96;
	M=26;
	for (int i=1;i<=n;++i){
		for (int j=0;j<=M;++j) c[j]=0;
		for (int j=0;j<two[n];++j) ++c[tp[rk[j]^two[i-1]]];
		for (int j=1;j<=M;++j) c[j]+=c[j-1];
		for (int j=two[n]-1;~j;--j) Rk[--c[tp[rk[j]^two[i-1]]]]=rk[j];
		for (int j=0;j<=M;++j) c[j]=0;
		for (int j=0;j<two[n];++j) ++c[tp[Rk[j]]];
		for (int j=1;j<=M;++j) c[j]+=c[j-1];
		for (int j=two[n]-1;~j;--j) rk[--c[tp[Rk[j]]]]=Rk[j];
		for (int j=0;j<=M;++j) c[j]=0;
		Rk[rk[0]]=0;
		for (int j=1;j<two[n];++j)
		    Rk[rk[j]]=Rk[rk[j-1]]+(tp[rk[j]]!=tp[rk[j-1]]||tp[rk[j]^two[i-1]]!=tp[rk[j-1]^two[i-1]]);
		for (int j=0;j<two[n];++j) tp[j]=Rk[j];
		M=Rk[rk[two[n]-1]];
	}
	for (int i=0;i<two[n];++i) cout<<S[rk[0]^i];
	return 0;
}

标签:int,two,sync,传送门,Xoration,基数排序,异或,Minimal
来源: https://www.cnblogs.com/Spare-No-Effort/p/16072542.html