【Luogu P1368】Minimal notation [template]

Title description

Title
Xiao Min and Xiao Yan are good friends.
They are playing a magical game called Minecraft MinecraftMinecraft

They are now making a long craft made of squares. But the squares are messy now, and due to the requirements of the machine, they can only put the leftmost square of this craft to the rightmost.

They think how beautiful the most beautiful handicraft can be with this one operation.

The way to compare the beauty of two handicrafts is to compare from the beginning. If the squares at the i-th position are different, then the one with smaller flaws will be more beautiful. If they are the same, then continue to compare the i+1th square. If all are the same, then these two crafts are just as beautiful.

Input format

An integer n in the first line represents the number of squares.

In the second line, there are n integers, and each integer outputs the value of the block defect degree from left to right.

Output format

A row of n integers represents the value of the defect degree from left to right of the most beautiful handicraft.

Sample input and output

Enter #1

10
10 9 8 7 6 5 4 3 2 1

Output #1

1 10 9 8 7 6 5 4 3 2

analysis:

The template of the minimum representation should normally be a string algorithm,
which is to find SSS Thelexicographically smallest isomorphic substringS 'S'S
If there is a string: "abcde": "abcde":"abcde" " b c d e a " "bcdea" "bcdea" " c d e a b " "cdeab" " c d e a b " are all its isomorphic substrings and so on... The
same reason is brought to this question, so I am very happy toseeit.
Usei, ji, ji and j aremessing aroundand update them

CODE:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define re register 
using namespace std;
int n,a[600005];
int MRA(int x[]) //最小表示法
{
    
    
	int i=1,j=2,k;
	while(i<=n&&j<=n)  //范围
	{
    
    
		for(k=0;k<=n&&x[i+k]==x[j+k];k++);  //数值相同 匹配长度k++
		//这个for相当于赋值+判断+统计
			if(x[i+k]>x[j+k])  //i~i+k-1不会有最小表示
			{
    
    
				i+=k+1;  //i指针更新
				if(i==j) i++;
			}else{
    
      //j~j+k-1不会有最小表示
				j+=k+1;  //j指针更新
				if(i==j) j++;
			}
	}
	return min(i,j);
}
int main(){
    
    
	scanf("%d",&n);
	for(re int i=1;i<=n;i++)
	{
    
    
		scanf("%d",&a[i]);
		a[i+n]=a[i];  //复制一遍
	}	
	int p=MRA(a);  //最小表示结果
	for(re int i=p;i<=p+n-1;i++)  //最小表示区间
		printf("%d ",a[i]);
	
	return 0;
} 

Guess you like

Origin blog.csdn.net/dgssl_xhy/article/details/109296542