Luogu P1368 【模板】最小表示法
https://www.luogu.com.cn/problem/P1368
题面
给定一个字符串,求出最小的循环表示
分析
先扩展两倍
给定两个起点\(i,j\),找到第一个\(a[i+k]!=a[j+k]\),判断大小
不妨假设\(a[i+k]>a[j+k]\)
则对于起点\(a\in [i,i+k]\)总会比起点\(b\in [j,j+k]\)劣
\(\therefore i=i+k+1\)
因为\((i,j)\)只加,所以均摊\(O(n)\)
#include<bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int n,a[N];
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]),a[i+n]=a[i];
}
int i=1,j=2;
while(i<=n&&j<=n) {
int k;
for(k=0;k<=n&&a[i+k]==a[j+k];k++);
if(k==n) {
for(int l=1;l<=n;l++) {
printf("%d ",a[l]);
}
return 0;
}
if(a[i+k]>a[j+k]) i+=k+1; else j+=k+1;
if(i==j) j++;
}
if(i>n) {
for(int k=j;k<=n;k++) printf("%d ",a[k]);
for(int k=1;k<j;k++) printf("%d ",a[k]);
} else {
for(int k=i;k<=n;k++) printf("%d ",a[k]);
for(int k=1;k<i;k++) printf("%d ",a[k]);
}
return 0;
}

浙公网安备 33010602011771号