经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
洛谷P3763 [TJOI2017]DNA(后缀数组 RMQ)
来源:cnblogs  作者:自为风月马前卒  时间:2018/11/29 9:27:49  对本文有异议

题意

题目链接

Sol

这题打死我也不会想到后缀数组的,应该会全程想AC自动机之类的吧

但知道这题能用后缀数组做之后应该就不是那么难了

首先把\(S\)\(S0\)拼到一起跑,求出Height数组

暴力枚举每个后缀是否能成为答案。

具体来说,每次比较当前后缀和\(S_0\)的lcp,如果长度\(< N\)的话就从不合法的位置继续匹配

rmq维护一下区间lcp最小值

BZOJ上被完美卡常

  1. // luogu-judger-enable-o2
  2. #include<bits/stdc++.h>
  3. using namespace std;
  4. const int MAXN = 2e5 + 10;
  5. const int INF = 2333;
  6. inline int read() {
  7. char c = getchar(); int x = 0, f = 1;
  8. while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
  9. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  10. return x * f;
  11. }
  12. int N, M, L, rak[MAXN], tax[MAXN], tp[MAXN], sa[MAXN], H[MAXN], f[MAXN][20], lg2[MAXN];
  13. char s[MAXN], s0[MAXN];
  14. void Qsort() {
  15. for(int i = 0; i <= M; i++) tax[i] = 0;
  16. for(int i = 1; i <= N; i++) tax[rak[i]]++;
  17. for(int i = 1; i <= M; i++) tax[i] += tax[i - 1];
  18. for(int i = N; i >= 1; i--) sa[tax[rak[tp[i]]]--] = tp[i];
  19. }
  20. void SuffixSort() {
  21. for(int i = 1; i <= N; i++) rak[i] = s[i], tp[i] = i; M = 233; Qsort();
  22. for(int w = 1, p = 0; p < N; w <<= 1, M = p) { p = 0;
  23. for(int i = 1; i <= w; i++) tp[++p] = N - i + 1;
  24. for(int i = 1; i <= N; i++) if(sa[i] > w) tp[++p] = sa[i] - w;
  25. Qsort(); swap(tp, rak); rak[sa[1]] = p = 1;
  26. for(int i = 2; i <= N; i++) rak[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++p;
  27. }
  28. for(int i = 1, k = 0; i <= N; i++) {
  29. if(k) k--; int j = sa[rak[i] - 1];
  30. while(s[i + k] == s[j + k]) k++;
  31. H[rak[i]] = k;
  32. }
  33. }
  34. void Pre() {
  35. for(int i = 1; i <= N; i++) f[i][0] = H[i];
  36. for(int j = 1; j <= 17; j++)
  37. for(int i = 1; i + (1 << j) - 1 <= N; i++) f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
  38. }
  39. int Query(int x, int y) {
  40. if(x > y) swap(x, y); x++;
  41. int k = lg2[y - x + 1];
  42. return min(f[x][k], f[y - (1 << k) + 1][k]);
  43. }
  44. int check(int x, int y, int dep) {
  45. if(dep == 3) return Query(rak[x], rak[y]);
  46. int num = Query(rak[x], rak[y]);
  47. num += check(x + num + 1, y + num + 1, dep + 1) + 1;
  48. return num;
  49. }
  50. void solve() {
  51. scanf("%s%s", s + 1, s0 + 1);
  52. L = strlen(s0 + 1); N = strlen(s + 1);
  53. for(int i = 1; i <= L; i++) s[N + i] = s0[i];
  54. N += L;
  55. SuffixSort(); Pre(); N -= L; int ans = 0;
  56. for(int i = 1; i <= N - L + 1; i++) if(check(i, N + 1, 0) >= L) ans++;
  57. printf("%d\n", ans);
  58. }
  59. int main() {
  60. //freopen("a.in", "r", stdin);
  61. lg2[1] = 0; for(int i = 2; i <= MAXN - 1; i++) lg2[i] = lg2[i >> 1] + 1;
  62. for(int T = read(); T; solve(), T--);
  63. return 0;
  64. }
  65. /*
  66. 2
  67. ATCGCCCTA
  68. CTTCA
  69. ATCGCCCTA
  70. CTTCA
  71. */
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号