版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/81782617
题目链接<https://cn.vjudge.net/problem/Gym-101667I>
题意:
每次给出数组T[]。问要满足从第k+1个数开始,数组T开始以p个数为一个循环,k+p最小是多少。如果存在多个k+p最小,输出p最小的方案。
题解:
首先要明白它所说的循环是什么,abcabc是以abc为一个循环。abcab也可以是以abc为一个循环,只是最后的c没有。
做法就是将数组倒过来,求一次kmp的next数组。利用结论p=i-next[i](循环节长度==当前长度 - next值)。然后枚举k的长度,就可以出结果了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=5e6+7;
int a[N],next[N],n;
void getnext(){
for(int i=0,j=2;j<=n;++j){
while(i&&a[j]!=a[i+1]) i=next[i];
if(a[j]==a[i+1]) i++;
next[j]=i;
}
}
int main(){
scanf("%d",&n);
for(int i=n;i>=1;i--)
scanf("%d",&a[i]);
getnext();
int ak=n,ap=n;
for(int i=1;i<=n;i++){
int p=i-next[i],k=n-i;
if(p+k<ak+ap) ak=k,ap=p;
else if(p+k==ak+ap&&p<ap) ak=k,ap=p;
}
printf("%d %d\n",ak,ap);
return 0;
}