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;
}
posted @ 2020-11-27 13:52  wwwsfff  阅读(113)  评论(0)    收藏  举报