最小表示法

模板傳送門
參考博客
算法流程:
把原串複製,接在後面。
記兩個指針p,qp,q。初始化p=1,q=2p=1,q=2
從兩個指針開始往後逐位比較。
a[p+k]==a[q+k]a[p+k]==a[q+k],則++k++k
若最後k==nk==n,說明原串只由一個字符組成,任意輸出即可。
否則此時kk滿足:a[p+k]!=a[q+k]a[p+k]!=a[q+k]

a[p+k]>a[q+k]a[p+k] > a[q+k],則移動ppp=p+k+1p=p+k+1
若此時p==qp==q,則++p++p,避免指針相同。
如果p>np>n,那麼退出,最小表示的起點即爲qq

a[p+k]<a[q+k]a[p+k] < a[q+k],同理。

那麼問題來了,空間爲什麼不開兩倍呢?

#include<bits/stdc++.h>
#define cs const
#define re register
namespace IO{
	cs int Rlen=1<<22|1;
	char buf[Rlen],*p1,*p2;
	inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
	template<typename T>
	inline T get(){
		char ch;T x;
		while(!isdigit(ch=gc()));x=ch^48;
		while(isdigit(ch=gc())) x=((x+(x<<2))<<1)+(ch^48);
		return x;
	}
	inline int gi(){return get<int>();}
}
using IO::gi;
cs int N=3e5+10;
int n,a[N<<1],p,q,k;
int main(){
	//freopen("1368.in","r",stdin);
	n=gi();
	for(int re i=1;i<=n;++i) a[n+i]=a[i]=gi();
	p=1,q=2;
	while(p<=n&&q<=n){
		for(k=0;k<n&&a[p+k]==a[q+k];++k);if(k==n) break;
		(a[p+k]>a[q+k])?(p+=k+1,p+=(p==q)):(q+=k+1,q+=(p==q));
	}for(int s=std::min(p,q),i=0;i<n;++i) printf("%d ",a[i+s]);
	return puts(""),0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章