codeforces round#259 div2 B题(KMP)

先上链接:http://codeforces.com/contest/454/problem/B


B. Little Pony and Sort by Shift
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

One day, Twilight Sparkle is interested in how to sort a sequence of integers a1, a2, ..., an in non-decreasing order. Being a young unicorn, the only operation she can perform is a unit shift. That is, she can move the last element of the sequence to its beginning:

a1, a2, ..., an → an, a1, a2, ..., an - 1.

Help Twilight Sparkle to calculate: what is the minimum number of operations that she needs to sort the sequence?

Input

The first line contains an integer n (2 ≤ n ≤ 105). The second line contains n integer numbers a1, a2, ..., an (1 ≤ ai ≤ 105).

Output

If it's impossible to sort the sequence output -1. Otherwise output the minimum number of operations Twilight Sparkle needs to sort it.

Sample test(s)
input
2
2 1
output
1
input
3
1 3 2
output
-1
input
2
1 2
output
0

       题意:给你n个数,要你给这n个数排序,排序成非递减的序列。但是排序的规则是每次只能把序列的最后一个数放到最前面。求组成非递减序列所需要最少的次数。如果不能组成,则输出-1.

       这道题我非常神奇的想到了用KMP去做,竟然过了。。。


先给出思路:假设能够排序成非递减序列,最多执行n次。那我就让它先执行n次。

      则我能让原始序列变成 2*n的长度   假如序列之前为 4 1 2 3 ,执行n次我可以假设它变成了 4 1 2 3 4 1 2 3。

然后用kmp算法找到 1 2 3 4的位置(当然是靠后面的位置),然后记录位置d, n - d就是它的执行次数,如果没有匹配到,就不能变成之前的样子。

     

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 100005
int ans[maxn], v[maxn], va[maxn + maxn];
int next[maxn];
int n, d;
using namespace std;
void getnext() {
	int j = 0;
	int k = -1;
	next[0] = -1;
	while(j < n) {
		if(k == -1 || v[j] == v[k]) {
			++k;
			++j;
			next[j] = k;
		} else k = next[k];
	}
}
void kmp() {
	int i = 0, j = 0;
	while(i < n + n) {
		if(j == -1 || va[i] == v[j]) {
			++i;
			++j;
		} else j = next[j];
		if(j == n) d =  i - j,j = next[j];
	}
}
int main() {
	while(scanf("%d", &n) != EOF) {
		for(int i = 0; i < n; ++i) {
			scanf("%d", &ans[i]);
			v[i] = ans[i];
		}
		d = -1;
		sort(v, v + n);
		for(int i = 0; i < n; ++i) va[i] = va[i + n] = ans[i];
		/**
		printf("ans = \n");
		for(int i = 0;i < n;++i) printf("%d ",ans[i]);
		printf("\n");
		for(int i = 0;i < n;++i) printf("%d ",v[i]);
		printf("\n");
		for(int i = 0;i < n+n;++i) printf("%d ",va[i]);printf("\n");
		**/
		getnext();
		kmp();

		if(d == -1)
		printf("%d\n",d);
		else
            printf("%d\n",n - d);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值