洛谷P1368 【模板】最小表示法
Description
求与S循环同构的所有字符串中字典序最小的字符串
Solution
考虑对于一对字符串
A
,
B
A,B
A,B, 它们在原字符串
S
S
S 中的起始位置分别为
i
,
j
i,j
i,j,且它们的前
k
k
k 个字符均相同,即
S
[
i
.
.
.
i
+
k
−
1
]
=
S
[
j
.
.
.
j
+
k
−
1
]
S[i...i+k-1]=S[j...j+k-1]
S[i...i+k−1]=S[j...j+k−1]
若
S
[
i
+
k
]
>
S
[
j
+
k
]
S[i+k]>S[j+k]
S[i+k]>S[j+k],则对于任意一个字符串
S
i
+
p
S_{i+p}
Si+p(表示以
i
+
p
i+p
i+p 为起始位置的字符串,
p
∈
[
0
,
k
]
)
p \in [0, k])
p∈[0,k]),字符串
S
j
+
p
S_{j+p}
Sj+p一定比它更优。
所以比较时可以跳过
[
i
,
i
+
k
]
[i,i+k]
[i,i+k],直接从
i
+
k
+
1
i+k+1
i+k+1开始继续比较
停止条件是
i
,
j
,
k
i,j,k
i,j,k中有一个
≥
n
≥n
≥n,因为这样就循环了,此时
m
i
n
(
i
,
j
)
min(i,j)
min(i,j)就是最终答案的起始位置
下面处理一个细节问题,为什么选
m
i
n
(
i
,
j
)
min(i,j)
min(i,j),而不用
c
h
e
c
k
check
check一下
①
k
=
n
k=n
k=n(
k
k
k每次只加一,所以不会大于),
i
,
j
i,j
i,j等价
②
i
≥
n
i≥n
i≥n
通过我们的比较过程,我们可以得知,在
m
a
x
(
i
,
j
)
max(i,j)
max(i,j)之前除
i
,
j
i,j
i,j的位置作起始位置一定不会比
i
,
j
i,j
i,j更优(用数规易证)
我们将操作后的
i
i
i记作
i
′
i'
i′
i
′
≥
n
i'≥n
i′≥n,上一步操作一定是
i
+
=
k
+
1
i+=k+1
i+=k+1,即
i
′
=
i
+
k
+
1
i'=i+k+1
i′=i+k+1,且此时
k
<
n
k<n
k<n
此时的
i
′
i'
i′与
i
′
−
n
i'-n
i′−n等价,由
k
<
n
k<n
k<n,有
i
′
−
n
≤
i
≤
m
a
x
(
i
,
j
)
i'-n≤i≤max(i,j)
i′−n≤i≤max(i,j),而
i
i
i本身就是要
o
u
t
out
out的,所以
i
′
o
u
t
!
i'\space out!
i′ out!
③
j
≥
n
j≥n
j≥n同理
Code
#include<bits/stdc++.h>
using namespace std;
#define gc getchar
inline int rd(){
int x=0,fl=1;char ch=gc();
for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
for (;48<=ch&&ch<=57;ch=gc())x=x*10+(ch^48);
return x*fl;
}
int n,i,j,k,t,s[300003];
int main(){
for (n=rd();i<n;i++) s[i]=rd();
for (i=0,j=1;i<n && j<n && k<n;){
t=s[(i+k)%n]-s[(j+k)%n];
if (!t) k++;
else (t>0?i:j)+=k+1,j+=(i==j),k=0;
}
i=min(i,j);
for (k=0;k<n;k++) printf("%d ",s[(i+k)%n]);
}
浙公网安备 33010602011771号