[bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式——后缀数组
2024-09-04 16:03:21
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();
}
最新文章
- Flexbox实现垂直水平居中
- PHP基础01:环境搭建
- tip use view.isineditmode() in your custom views to skip code when shown in eclipse
- 为什么要用Java泛型
- Web Server PROPFIND Method internal IP Discosure
- java中的Unicode中文转义
- phalcon——Paginator分页
- 数据结构与算法 —— 链表linked list(01)
- 关于html+ashx开发中几个问题的解决方法
- js计算两个日期的月份差?
- svn linux 服务器的搭建
- Git 几个常用操作
- CANOE入门(二)
- Beyond Compare脚本:命令行批量比较文件并生成html格式的差异报告
- linux开启nscd服务缓存加速
- python中的Lock
- 第三周JAVA程序设计基础学习总结
- 【bzoj2333 &; luoguP3273】棘手的操作(线段树合并)
- CycloneII之EDA及学术开发功能描述
- JAVA list 列表 字典 dict
热门文章
- **leetcode笔记--4 Sum of Two Integers
- 给虚拟机发送键盘按键key
- 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现
- 分词(Tokenization) - NLP学习(1)
- pexpect获取远端命令执行结果
- ISAP 最大流 最小割 模板
- HDU 4587 TWO NODES(割点)(2013 ACM-ICPC南京赛区全国邀请赛)
- 软件工程项目组Z.XML会议记录 2013/09/25
- java rmi浅谈
- MongoDB Linux下的安装和启动