这是一道后缀匹配的模板题
我们只需要将height算出来
然后二分一下答案就可以了
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn=1010000;
int data[maxn];
int rank[maxn];
int tot[maxn];
int sa[maxn];
int pas[maxn];
int len,n,m;
int height[maxn];
int k;
void build_Sa()
{
m=150;
for(int i=0;i<n;i++)
rank[i]=data[i],tot[data[i]]+=1;
for(int i=1;i<=m;i++)
tot[i]+=tot[i-1];
for(int i=n-1;i>=0;i--)
sa[--tot[rank[i]]]=i;
for(int k=1;k<=n;k<<=1)
{
int num=0;
for(int i=n-k;i<n;i++) pas[num++]=i;
for(int i=0;i<n;i++)
if(sa[i]>=k) pas[num++]=sa[i]-k;
for(int i=0;i<=m;i++) tot[i]=0;
for(int i=0;i<n;i++) tot[rank[i]]+=1;
for(int i=1;i<=m;i++) tot[i]+=tot[i-1];
for(int i=n-1;i>=0;i--)
sa[--tot[rank[pas[i]]]]=pas[i],pas[i]=0;
swap(pas,rank);
num=1;rank[sa[0]]=1;
for(int i=1;i<n;i++)
if(pas[sa[i]]!=pas[sa[i-1]]||pas[sa[i]+k]!=pas[sa[i-1]+k])
rank[sa[i]]=++num;
else
rank[sa[i]]=num;
if(num>=n) break;
m=num;
}
}
void build_LCP()
{
int h=0;
/*for(int i=0;i<n;i++) pas[sa[i]]=i;
for(int i=0;i<n;i++)
{
if(!pas[i]) continue;
int j=sa[pas[i]-1];
if(h) h--;
while(data[j+h]==data[i+h]&&j+h<n&&i+h<n) h++;
height[pas[i]]=h;
}*/
for(int i=0;i<n;i++)
{
if(rank[i]-1==0) continue;
int j=sa[rank[i]-2];
if(h) h-=1;
while(j+h<n&&i+h<n)
if(data[j+h]!=data[i+h]) break;
else h+=1;
height[rank[i]]=h;
}
}
bool check(int val)
{
int now=0;
for(int i=0;i<=n;i++)
{
if(height[i]>=val) now+=1;
else now=0;
if(now>=k-1) return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++) scanf("%d",&data[i]);
int l=1,r=n,mid;
build_Sa();
build_LCP();
while(l+1<r)
{
mid=(l+r)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%d", check(r) ? r : l );
}
/*
8 2
1
2
3
2
3
2
3
1
12323231
*/