【洛谷 P1368】最小表示法[模板]

题目描述

题目
小敏和小燕是一对好朋友。
他们正在玩一种神奇的游戏,叫 M i n e c r a f t Minecraft Minecraft

他们现在要做一个由方块构成的长条工艺品。但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工艺品最左边的方块放到最右边。

他们想,在仅这一个操作下,最漂亮的工艺品能多漂亮。

两个工艺品美观的比较方法是,从头开始比较,如果第 i 个位置上方块不一样那么谁的瑕疵度小,那么谁就更漂亮,如果一样那么继续比较第 i+1 个方块。如果全都一样,那么这两个工艺品就一样漂亮。

输入格式

第一行一个整数 n,代表方块的数目。

第二行 n 个整数,每个整数按从左到右的顺序输出方块瑕疵度的值。

输出格式

一行 n 个整数,代表最美观工艺品从左到右瑕疵度的值。

输入输出样例

输入 #1

10
10 9 8 7 6 5 4 3 2 1

输出 #1

1 10 9 8 7 6 5 4 3 2

分析:

最小表示法的模板 正常应该是字符串的算法
也就是求 S S S字典序最小同构子串 S ′ S' S
如有一个串为 : " a b c d e " :"abcde" :"abcde" " b c d e a " "bcdea" "bcdea" " c d e a b " "cdeab" "cdeab"都是它的同构子串 以此类推……
同理带到这道题也就非常喜闻乐见
i , j i,j ij两个指针瞎搞一通 然后更新它们

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;
} 

猜你喜欢

转载自blog.csdn.net/dgssl_xhy/article/details/109296542
今日推荐