原题
题意不再赘述。可以二分答案把每个子串哈希之后统计出现个数……就好了……哈希方法不明白的可以参照白书3.4.3。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define maxn 20010
typedef unsigned long long LL;
using namespace std;
const int p=2000007;
int K,cnt[p];
LL s[maxn],H[maxn],sum[maxn],da[maxn],f[maxn];
int head[p],n;
struct Hash{
LL val;
int next;
}h[p];
int tot;
int hash(LL x){
int a=x%p;
for(int i=head[a];i;i=h[i].next)
if(h[i].val==x)return i;
h[++tot]=(Hash){x,head[a]};
return head[a]=tot;
}
bool judge(int x){
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n-x+1;i++)if(++cnt[hash(H[i]-s[x]*H[i+x])]>=K)return 1;//对字符串的哈希值再次哈希并统计个数
return 0;
}
int main(){
freopen("3261.in","r",stdin);
freopen("wode.out","w",stdout);
s[0]=1;
for(int i=1;i<=maxn;i++)s[i]=s[i-1]*17;
while(scanf("%d%d",&n,&K)==2){
for(int i=1;i<=n;i++)scanf("%I64u",&da[i]);
for(int i=n;~i;i--)H[i]=H[i+1]*17+da[i];
int l=1,r=n,ans=0;
while(l<=r){
memset(head,0,sizeof(head));
int m=(l+r)/2;
if(judge(m)){
l=m+1;
ans=m;
}
else r=m-1;
}
printf("%d\n",ans);
}
return 0;
}