模板传送门
参考博客
算法流程:
把原串复制,接在后面。
记两个指针
p
,
q
p,q
p,q。初始化
p
=
1
,
q
=
2
p=1,q=2
p=1,q=2。
从两个指针开始往后逐位比较。
若
a
[
p
+
k
]
=
=
a
[
q
+
k
]
a[p+k]==a[q+k]
a[p+k]==a[q+k],则
+
+
k
++k
++k。
若最后
k
=
=
n
k==n
k==n,说明原串只由一个字符组成,任意输出即可。
否则此时
k
k
k满足:
a
[
p
+
k
]
!
=
a
[
q
+
k
]
a[p+k]!=a[q+k]
a[p+k]!=a[q+k]
若
a
[
p
+
k
]
>
a
[
q
+
k
]
a[p+k] > a[q+k]
a[p+k]>a[q+k],则移动
p
p
p:
p
=
p
+
k
+
1
p=p+k+1
p=p+k+1
若此时
p
=
=
q
p==q
p==q,则
+
+
p
++p
++p,避免指针相同。
如果
p
>
n
p>n
p>n,那么退出,最小表示的起点即为
q
q
q。
若 a [ p + k ] < a [ q + k ] 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;
}