Brief Description

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

Algorithm Design

先二分答案,然后将后缀分成若干组。判断有没有一个组的后缀个数不小于k。如果有,那么存在k个相同的子串满足条件,否则不存在。这个做法的时间复杂度为\(\Theta(nlgn)\).

Code

#include <cstdio>
const int maxn = 20010;
int a[maxn], sa[2][maxn], rank[2][maxn], height[maxn];
int n, K, k, m, p, q;
int v[1000100];
void calc(int sa[maxn], int rank[maxn], int Sa[maxn], int Rank[maxn]) {
for (int i = 1; i <= n; i++)
v[rank[sa[i]]] = i;
for (int i = n; i >= 1; i--)
if (sa[i] > k)
Sa[v[rank[sa[i] - k]]--] = sa[i] - k;
for (int i = n - k + 1; i <= n; i++)
Sa[v[rank[i]]--] = i;
for (int i = 1; i <= n; i++)
Rank[Sa[i]] = Rank[Sa[i - 1]] + (rank[Sa[i]] != rank[Sa[i - 1]] ||
rank[Sa[i] + k] != rank[Sa[i - 1] + k]);
}
void calh(int sa[maxn], int rank[maxn]) {
int i, j, k = 0;
for (i = 1; i <= n; height[rank[i++]] = k)
for (k ? k-- : 0, j = sa[rank[i] - 1]; a[i + k] == a[j + k]; k++)
;
return;
}
void da() {
m = 1000010, p = 0, q = 1, k = 1;
for (int i = 1; i <= n; i++)
v[a[i]]++;
for (int i = 1; i <= m; i++)
v[i] += v[i - 1];
for (int i = 1; i <= n; i++)
sa[p][v[a[i]]--] = i;
for (int i = 1; i <= n; i++)
rank[p][sa[p][i]] =
rank[p][sa[p][i - 1]] + (a[sa[p][i - 1]] != a[sa[p][i]]);
while (k < n) {
calc(sa[p], rank[p], sa[q], rank[q]);
p ^= 1;
q ^= 1;
k <<= 1;
}
calh(sa[p], rank[p]);
}
bool check(int x) {
int l = 1, r = 1;
for (int i = 2; i <= n + 1; i++)
if (height[i] >= x)
r++;
else if (r - l + 1 >= K)
return true;
else {
l = i;
r = i;
continue;
}
return false;
}
void solve() {
int l = 0, r = n;
while (r - l > 1) {
int mid = (l + r) >> 1;
if (check(mid))
l = mid;
else
r = mid;
}
printf("%d\n", check(r) ? r : l);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("input", "r", stdin);
#endif
scanf("%d %d", &n, &K);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
da();
solve();
}

最新文章

  1. Flexbox实现垂直水平居中
  2. PHP基础01:环境搭建
  3. tip use view.isineditmode() in your custom views to skip code when shown in eclipse
  4. 为什么要用Java泛型
  5. Web Server PROPFIND Method internal IP Discosure
  6. java中的Unicode中文转义
  7. phalcon——Paginator分页
  8. 数据结构与算法 —— 链表linked list(01)
  9. 关于html+ashx开发中几个问题的解决方法
  10. js计算两个日期的月份差?
  11. svn linux 服务器的搭建
  12. Git 几个常用操作
  13. CANOE入门(二)
  14. Beyond Compare脚本:命令行批量比较文件并生成html格式的差异报告
  15. linux开启nscd服务缓存加速
  16. python中的Lock
  17. 第三周JAVA程序设计基础学习总结
  18. 【bzoj2333 &amp; luoguP3273】棘手的操作(线段树合并)
  19. CycloneII之EDA及学术开发功能描述
  20. JAVA list 列表 字典 dict

热门文章

  1. **leetcode笔记--4 Sum of Two Integers
  2. 给虚拟机发送键盘按键key
  3. 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现
  4. 分词(Tokenization) - NLP学习(1)
  5. pexpect获取远端命令执行结果
  6. ISAP 最大流 最小割 模板
  7. HDU 4587 TWO NODES(割点)(2013 ACM-ICPC南京赛区全国邀请赛)
  8. 软件工程项目组Z.XML会议记录 2013/09/25
  9. java rmi浅谈
  10. MongoDB Linux下的安装和启动