题目链接
题目大意:求对于所有的k,数列去掉前k项后剩余部分的最小循环节p,k+p的最小值。
思路:枚举k,计算a[k+1…n]的最小循环节p,维护k+p的最小值。
tips:求a[k+1…n]的最小循环节p时,将数列翻转。
#include<bits/stdc++.h>
#define FAST ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define INF 0x3f3f3f3f
typedef long long ll;
const int maxn = 1e6+5;
using namespace std;
int n,ans_p,ans_k;
int a[maxn],p[maxn];
void get() //求前缀函数
{
int j=0;
for (int i=2; i<=n; i++)
{
while(a[j+1]!=a[i] && j) j=p[j];
if (a[j+1]==a[i]) j++;
p[i]=j;
}
}
int main()
{
FAST;
while(cin>>n)
{
ans_p=ans_k=INF;
for (int i=1; i<=n; i++) cin>>a[i];
reverse(a+1,a+n+1);
get();
for (int k=1; k<=n; k++)
{
int pp=k-p[k];
if (ans_p+ans_k>n-k+pp) ans_p=pp, ans_k=n-k;
}
cout<<ans_k<<' '<<ans_p<<endl;
}
return 0;
}