1. 程式人生 > >Gym 101667I Slot Machines (2017-2018 ACM-ICPC, Asia Daejeon Regional Contest I題)

Gym 101667I Slot Machines (2017-2018 ACM-ICPC, Asia Daejeon Regional Contest I題)

傳送門:http://codeforces.com/gym/101667

Problem I Slot Machines Time Limit: 2 Seconds

題意:陣列a有n個數字,數字範圍0~999999希望求一組最小的k+p,使得任意i>k,都有a[i]=a[i+p],若兩組k+p大小相等,取p較小的

思路:p為迴圈節,也就是說要求最小的週期。將a序列倒序,求出next陣列。這裡參考了https://blog.csdn.net/infinity_edge/article/details/79079348的題解,這和kmp裡的next有些不一樣,next[i]代表倒序後的第i位的數字往前可以追溯到第next[i]位(有點難說清)。

程式碼:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxv=1e6+6;

int a[maxv],b[maxv],nt[maxv];
int n,m,k,p;
int main()
{
    scanf("%d", &n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)
		b[n-i+1]=a[i];
	nt[1]=0;
	for(int i=1;i<n;i++)
	{
		int j=nt[i];
		while(j&&b[j+1]!=b[i+1])
			j=nt[j];
		if(b[i+1]==b[j+1])
			nt[i+1]=j+1;
		else
			nt[i+1]=0;
	}
    int ans=inf;
	for(int i=1;i<=n;i++)
	{
		int now=(n-i+1-nt[n-i+1]);
		if(ans>i+now||(i+now==ans&&now<p))
		{
			ans=i+now;
			k=i-1;
			p=now;
		}
	}
    printf("%d %d\n", k, p);
    return 0;
}