题目大意:

给定一个数组,求一个最大的长度的子串至少出现过k次

一个子串出现多次,也就是说必然存在2个子串间的前缀长度为所求的值

通过二分答案,通过线性扫一遍,去判断出现次数,也就是说每次遇见一个height[i] , 出现次数就加1,否则重置为1

 #include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = ;
int rank[N] , sa[N] , height[N];
int wa[N] , wb[N] , wsf[N] , wv[N];
int a[N]; int cmp(int *r , int a , int b , int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
} void getSa(int *r , int *sa , int n , int m)
{
int i,j,p;
int *x=wa , *y=wb , *t;
for(i= ; i<m ; i++) wsf[i]=;
for(i= ; i<n ; i++) wsf[x[i]=r[i]]++;
for(i= ; i<m ; i++) wsf[i] += wsf[i-];
for(i=n- ; i>= ; i--) sa[--wsf[x[i]]]=i; p=;
for(j= ; p<n ; j*= , m=p){
for(p= , i=n-j ; i<n ; i++) y[p++]=i;
for(i= ; i<n ; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i= ; i<n ; i++) wv[i]=x[y[i]];
for(i= ; i<m ; i++) wsf[i]=;
for(i= ; i<n ; i++) wsf[wv[i]]++;
for(i= ; i<m ; i++) wsf[i]+=wsf[i-];
for(i=n- ; i>= ; i--) sa[--wsf[wv[i]]]=y[i]; t=x,x=y,y=t;
x[sa[]]=;
for(p= , i= ; i<n ; i++)
x[sa[i]] = cmp(y , sa[i-] , sa[i] , j)?p-:p++;
}
return ;
} void getHeight(int *r , int *sa , int n)
{
for(int i= ; i<=n ; i++) rank[sa[i]]=i;
int k=;
int j;
for(int i= ; i<n ; height[rank[i++]]=k)
for(k?k--: , j=sa[rank[i]-] ; r[i+k]==r[j+k] ; k++);
return;
} bool check(int m , int n , int k)
{
int cnt=;
for(int i= ; i<=n ; i++){
if(height[i]>=m){
cnt++;
// cout<<"here: "<<m<<" "<<sa[i]<<" "<<sa[i-1]<<endl;
if(cnt>=k) return true;
}
else {cnt=;if(cnt>=k) return true;}
}
return false;
} int main()
{
// freopen("a.in" , "r" , stdin);
int n,k;
while(~scanf("%d%d" , &n , &k))
{
int maxn = ;
for(int i= ; i<n ; i++){
scanf("%d" , a+i);
a[i]++;
maxn = max(maxn , a[i]);
}
a[n]=;
getSa(a , sa , n+ , maxn+);
getHeight(a , sa , n); int l= , r=n , ans=;
while(l <= r){
int m=(l+r)>>;
if(check(m,n,k)){
ans = m;
l=m+;
}else r=m-;
}
printf("%d\n" , ans);
}
return ;
}

最新文章

  1. JavaEE Spring
  2. 【UML】UML基础知识
  3. sql实现分页
  4. 【剑指offer 面试题34】丑数
  5. 最近看了点C++,分享一下我的进度吧!
  6. SSM框架入门和搭建 十部曲
  7. MVC自学第一课
  8. HDU 1348 Wall
  9. linux 下 openssl 编译和交叉编译
  10. angularJS 系列(六)---$emit(), $on(), $broadcast()的使用
  11. HDU 3652(数位DP)
  12. 【爆料】-《阿伯丁大学毕业证书》AU一模一样原件
  13. jsplumb 中文教程
  14. js-模块化(三大模块化规范)
  15. jinfo
  16. 域渗透之通过DCSync获取权限并制作黄金票据
  17. 从Firebird2.5 迁移到 Firebird3.0 手记
  18. putty安装和使用
  19. Servlet上传下载
  20. JS前端创建CSV或Excel文件并浏览器导出下载

热门文章

  1. 用java打印输出九九乘法表
  2. 移动端rem单位用法
  3. LN : leetcode 646 Maximum Length of Pair Chain
  4. 手机端左右滑动,不用写js(只有页面切换到移动端可以看)
  5. 使用VirtualBox的时候虚拟机无法ping通windows主机,但是主机可以ping通虚拟机
  6. python与shell通过微信企业号发送消息
  7. iTOP-4418/6818开发板支持双屏异显,双屏同显
  8. fedora下yum安装gnome和kde桌面 (有问题 )
  9. CREATE FUNCTION - 定义一个新函数
  10. chvt - 修改虚拟终端的前台环境