题意:

给定一个字符串,求至少出现k 次的最长重复子串,这k 个子串可以重叠。

分析:

先二分答案,然后将后缀分成若干组。

不同的是,这里要判断的是有没有一个组的后缀个数不小于k。

如果有,那么存在k 个相同的子串满足条件,否则不存在。这个做法的时间复杂度为O(nlogn)。

// File Name: 3261.cpp
// Author: Zlbing
// Created Time: 2013年09月04日 星期三 21时21分51秒 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)
//rank从0开始
//sa从1开始,因为最后一个字符(最小的)排在第0位
//height从2开始,因为表示的是sa[i-1]和sa[i]
const int MAXN=1e6+;
int rank[MAXN],sa[MAXN],X[MAXN],Y[MAXN],height[MAXN],s[MAXN];
int buc[MAXN];
void calheight(int n) {
int i , j , k = ;
for(i = ; i <= n ; i++) rank[sa[i]] = i;
for(i = ; i < n ; height[rank[i++]] = k)
for(k?k--: , j = sa[rank[i]-] ; s[i+k] == s[j+k] ; k++);
}
bool cmp(int *r,int a,int b,int l) {
return (r[a] == r[b] && r[a+l] == r[b+l]);
}
void suffix(int n,int m = ) {
int i , l , p , *x = X , *y = Y;
for(i = ; i < m ; i ++) buc[i] = ;
for(i = ; i < n ; i ++) buc[ x[i] = s[i] ] ++;
for(i = ; i < m ; i ++) buc[i] += buc[i-];
for(i = n - ; i >= ; i --) sa[ --buc[ x[i] ]] = i;
for(l = ,p = ; p < n ; m = p , l *= ) {
p = ;
for(i = n-l ; i < n ; i ++) y[p++] = i;
for(i = ; i < n ; i ++) if(sa[i] >= l) y[p++] = sa[i] - l;
for(i = ; i < m ; i ++) buc[i] = ;
for(i = ; i < n ; i ++) buc[ x[y[i]] ] ++;
for(i = ; i < m ; i ++) buc[i] += buc[i-];
for(i = n - ; i >= ; i --) sa[ --buc[ x[y[i]] ] ] = y[i];
for(swap(x,y) , x[sa[]] = , i = , p = ; i < n ; i ++)
x[ sa[i] ] = cmp(y,sa[i-],sa[i],l) ? p- : p++;
}
calheight(n-);//后缀数组关键是求出height,所以求sa的时候顺便把rank和height求出来
}
int n,k;
bool judge(int x)
{
int cnt=;
for(int i=;i<=n;i++)
{
if(height[i]>=x)
cnt++;
else cnt=;
if(cnt>=k)
return true;
}
return false;
}
int main() {
while(~scanf("%d%d",&n,&k))
{
REP(i,,n-)
scanf("%d",&s[i]);
REP(i,,n-)s[i]++;
s[n]=;
suffix(n+,);
int l=,r=n,mid;
int ans=-;
while(l<=r)
{
mid=l+(r-l+)/;
if(judge(mid))
{
ans=max(mid,ans);
l=mid+;
}
else r=mid-;
}
printf("%d\n",ans);
} return ;
}

最新文章

  1. time &amp; datetime
  2. 你的C#代码是怎么跑起来的(二)
  3. Bootstrap Modals(模态框)
  4. Log4Net 配置StmpAppender
  5. Eclipse使用jre的原理与配置
  6. hibernate Java 时间和日期类型 Hibernate 制图
  7. JAVA实用案例之验证码开发
  8. OpenCV提取显示一张图片(或者视频)的R,G,B颜色分量
  9. R语言数据类型
  10. PageHelper补充
  11. [Linux性能调优] 磁盘I/O队列调度策略
  12. 【转载】Android RecyclerView 使用完全解析 体验艺术般的控件
  13. 【LeetCode每天一题】Permutations(排列组合)
  14. jar中META-INF
  15. 第 3 章 镜像 - 017 - RUN vs CMD vs ENTRYPOINT
  16. android 8.0 intent安装apk失败屏幕闪过
  17. Node.js文件操作一
  18. php中常用$_SERVER的用法
  19. 使用 python 管理 mysql 开发工具箱 - 2
  20. KVM下raw和qcow2格式磁盘文件IO测试

热门文章

  1. bluetooth-蓝牙事件监听
  2. windows下安装redis和php的redis扩展
  3. 2进制,16进制,BCD,ascii,序列化对象相互转换
  4. QT Windows下生成动态链接库
  5. jdk配置及maven配置
  6. (转)兼容主流浏览器的CSS透明代码
  7. 自己写的自动生成动态边框的jquery小插件
  8. 转-SecureCRT设置
  9. 段落排版--缩进(text-indent)
  10. 【转】WF4.0 (基础篇)