Repeats (spoj 687)
来源:互联网 发布:撒贝宁老婆二婚 知乎 编辑:程序博客网 时间:2024/05/21 10:19
题意:给你一串字符串,求重复次数最多的连续重复子串。例如
题解:参考论文上的解法,先枚举长度
#include <stdio.h>#include <string.h>#include <algorithm>#include <stdlib.h>#include <iostream>#define LL long longusing namespace std;const int Max = 50000 + 100;void radix(int *str, int *a, int *b, int n, int m) { static int count[Max]; for (int i = 0; i <= m; i++)count[i] = 0; for (int i = 0; i < n; i++)++count[str[a[i]]]; for (int i = 1; i <= m; i++)count[i] += count[i - 1]; for (int i = n - 1; i >= 0; i--)b[--count[str[a[i]]]] = a[i];}void suffix_array(int *str, int *sa, int n, int m) {//求sa数组 static int rank[Max], a[Max], b[Max]; for (int i = 0; i < n; i++)rank[i] = i; radix(str, rank, sa, n, m); rank[sa[0]] = 0; for (int i = 1; i < n; i++)rank[sa[i]] = rank[sa[i - 1]] + (str[sa[i]] != str[sa[i - 1]]); for (int i = 0; 1 << i < n; i++) { for (int j = 0; j < n; j++) { a[j] = rank[j] + 1; b[j] = j + (1 << i) >= n ? 0 : rank[j + (1 << i)] + 1; sa[j] = j; } radix(b, sa, rank, n, n); radix(a, rank, sa, n, n); rank[sa[0]] = 0; for (int j = 1; j < n; j++) { rank[sa[j]] = rank[sa[j - 1]] + (a[sa[j - 1]] != a[sa[j]] || b[sa[j - 1]] != b[sa[j]]); } }}void calc_height(int *str, int *sa, int *h, int n) {//求height数组 static int rank[Max]; int k = 0; h[0] = 0; for (int i = 0; i < n; i++)rank[sa[i]] = i; for (int i = 0; i < n; i++) { k = k == 0 ? 0 : k - 1; if (rank[i] != 0) while (str[i + k] == str[sa[rank[i] - 1] + k])++k; h[rank[i]] = k; }}int str[Max], sa[Max], h[Max], ranks[Max];char data[Max];int mm[Max], RMQ[Max];int best[20][Max];void initRMQ(int n) {//初始化RMQ为求lcp做准备 mm[0] = -1; for (int i = 1; i <= n; i++) { mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1]; } for (int i = 1; i <= n; i++)best[0][i] = i; for (int i = 1; i <= mm[n]; i++) for (int j = 1; j + (1 << i) - 1 <= n; j++) { int a = best[i - 1][j]; int b = best[i - 1][j + (1 << (i - 1))]; if (RMQ[a] < RMQ[b])best[i][j] = a; else best[i][j] = b; }}int askRMQ(int a, int b) { int t; t = mm[b - a + 1]; b -= (1 << t) - 1; a = best[t][a]; b = best[t][b]; return RMQ[a] < RMQ[b] ? a : b;}int lcp(int a, int b) {//直接求得lcp a = ranks[a]; b = ranks[b]; if (a > b)swap(a, b); return h[askRMQ(a + 1, b)];}char get_char() { char ans; while (1) { ans = getchar(); if (ans != ' ' && ans != '\n' && ans != '\r' && ans != '\t') return ans; }}int main() { int T; scanf("%d", &T); while (T--) { int n, m = -1; scanf("%d", &n); for (int a = 0; a < n; a++) { str[a] = get_char(); m = max(str[a], m); } str[n] = 0; suffix_array(str, sa, n, m);//套的板子 calc_height(str, sa, h, n); for (int i = 1; i <= n; i++)RMQ[i] = h[i]; for (int i = 0; i < n; i++)ranks[sa[i]] = i; initRMQ(n); int ans = 0; for (int l = 1; l < n; l++) { for (int i = 0; i + l < n; i += l) { int k = lcp(i, i + l); int r = k / l + 1; int t = i - (l - k % l); if (t >= 0 && k % l != 0 && lcp(t, t + l) >= k)r++;//当往后不够一个长为l的子串时, 判断往前是否最少有t个(t和最后余下的不够l的字符数相加等于l)字符匹配 if (r > ans)ans = r; } } printf("%d\n", ans); } return 0;}
阅读全文
0 0
- Repeats (spoj 687)
- spoj 687 repeats
- spoj 687 Repeats//后缀数组
- Repeats SPOJ
- SPOJ 687 REPEATS Repeats 后缀数组 + RMQ预处理
- SPOJ 687 Repeats 后缀数组+暴力+rmq
- spoj 687. Repeats
- SPOJ REPEATS SA
- 【后缀数组】SPOJ REPEATS
- SPOJ REPEATS(后缀数组)
- SPOJ REPEATS 后缀数组
- spoj Repeats 后缀数组
- SPOJ题目687 Repeats(后缀数组+RMQ求重复次数最多的子串的重复次数)
- SPOJ 687. Repeats(后缀数组)
- SPOJ-REPEATS之后缀数组
- SPOJ 687 Repeats (后缀数组+RMQ 重复次数最多的连续重复子串)
- Repeats SPOJ (后缀数组,寻找一个重复次数最多的子串)
- SPOJ687---REPEATS - Repeats(后缀数组+RMQ)
- 第六单元
- Reflection2017.10.9
- 基于OpenCV的视频图像组态 (3):常见PPT动画1
- C# ASCII与字符串间相互转换
- 如何通过域名访问阿里云部署的springboot项目
- Repeats (spoj 687)
- Spring MVC简单小结
- Python findall 和 match 和 search 的区别
- 为什么SQL正在击败NoSQL,这对未来的数据意味着什么
- hdu 3790 最短路径问题(Dijkstra多条件判断)
- http状态码
- Python3爬虫入门学习
- 训练日记-28
- [JAVA学习]shape绘画图形代码分析