1044.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * @Description:
  3. * @Version: 1.0
  4. * @Autor: zhuyijun
  5. * @Date: 2021-12-23 14:37:52
  6. * @LastEditTime: 2021-12-28 17:13:01
  7. */
  8. /*
  9. 1044. 最长重复子串
  10. 给你一个字符串 s ,考虑其所有 重复子串 :即,s 的连续子串,在 s 中出现 2
  11. 次或更多次。这些出现之间可能存在重叠。
  12. 返回 任意一个 可能具有最长长度的重复子串。如果 s 不含重复子串,那么答案为 "" 。
  13. 示例 1:
  14. 输入:s = "banana"
  15. 输出:"ana"
  16. 示例 2:
  17. 输入:s = "abcd"
  18. 输出:""
  19. */
  20. #include <bits/stdc++.h>
  21. using namespace std;
  22. class SuffixArray {
  23. public:
  24. using size_type = unsigned;
  25. using pointer = size_type*;
  26. using const_pointer = const size_type*;
  27. const_pointer sa, rk, ht;
  28. private:
  29. std::unique_ptr<size_type[]> data;
  30. private:
  31. template <typename S>
  32. inline static bool substring_equal(const S& s, size_type p1, size_type p2,
  33. size_type len) {
  34. for (size_type i = 0; i < len; ++i)
  35. if (s[p1 + i] != s[p2 + i]) return false;
  36. return true;
  37. }
  38. template <typename S>
  39. inline static void induced_sort(const S& s, pointer sa, bool* type,
  40. pointer pos, pointer lbuk, pointer sbuk,
  41. size_type n, size_type m, size_type n0) {
  42. std::fill_n(sa, n, 0);
  43. lbuk[0] = 0;
  44. for (size_type i = 1; i < m; ++i) lbuk[i] = sbuk[i - 1];
  45. for (size_type i = n0; i-- > 0;) sa[--sbuk[s[pos[i]]]] = pos[i];
  46. sbuk[m - 1] = n;
  47. for (size_type i = 1; i < m; ++i) sbuk[i - 1] = lbuk[i];
  48. sa[lbuk[s[n - 1]]++] = n - 1;
  49. for (size_type i = 0; i < n; ++i)
  50. if (sa[i] > 0 && !type[sa[i] - 1]) sa[lbuk[s[sa[i] - 1]]++] = sa[i] - 1;
  51. lbuk[0] = 0;
  52. for (size_type i = 1; i < m; ++i) lbuk[i] = sbuk[i - 1];
  53. for (size_type i = n; i-- > 0;)
  54. if (sa[i] > 0 && type[sa[i] - 1]) sa[--sbuk[s[sa[i] - 1]]] = sa[i] - 1;
  55. }
  56. template <typename S>
  57. inline static void sais(const S& s, pointer sa, bool* type, pointer len,
  58. pointer pos, pointer lbuk, pointer sbuk, size_type n,
  59. size_type m) {
  60. type[n - 1] = false;
  61. for (size_type i = n - 1; i-- > 0;)
  62. type[i] = s[i] != s[i + 1] ? s[i] < s[i + 1] : type[i + 1];
  63. size_type n0 = 0;
  64. for (size_type i = 1; i < n; ++i)
  65. if (!type[i - 1] && type[i]) pos[n0++] = i;
  66. std::fill_n(len, n, 0);
  67. for (size_type p = n - 1, i = n0; i-- > 0; p = pos[i])
  68. len[pos[i]] = p - pos[i] + 1;
  69. std::fill_n(sbuk, m, 0);
  70. for (size_type i = 0; i < n; ++i) ++sbuk[s[i]];
  71. for (size_type i = 1; i < m; ++i) sbuk[i] += sbuk[i - 1];
  72. induced_sort(s, sa, type, pos, lbuk, sbuk, n, m, n0);
  73. sbuk[m - 1] = n;
  74. for (size_type i = 1; i < m; ++i) sbuk[i - 1] = lbuk[i];
  75. size_type m0 = -1;
  76. size_type ppos = -1, plen = 0;
  77. for (size_type i = 0; i < n; ++i) {
  78. if (len[sa[i]] == 0) continue;
  79. if (len[sa[i]] != plen || !substring_equal(s, sa[i], ppos, plen)) ++m0;
  80. plen = len[sa[i]];
  81. len[sa[i]] = m0;
  82. ppos = sa[i];
  83. }
  84. pointer s0 = sa;
  85. pointer sa0 = sa + n0;
  86. for (size_type i = 0; i < n0; ++i) s0[i] = len[pos[i]];
  87. if (++m0 < n0)
  88. sais(s0, sa0, type + n, len, pos + n0, lbuk, lbuk + n0, n0, m0);
  89. else
  90. for (size_type i = 0; i < n0; ++i) sa0[s0[i]] = i;
  91. for (size_type i = 0; i < n0; ++i) pos[i + n0] = pos[sa0[i]];
  92. induced_sort(s, sa, type, pos + n0, lbuk, sbuk, n, m, n0);
  93. }
  94. public:
  95. template <typename S>
  96. SuffixArray(const S& s, size_type n, size_type m)
  97. : data(std::make_unique<size_type[]>(3 * n)) {
  98. const auto type = std::make_unique<bool[]>(2 * n);
  99. const auto lbuk = std::make_unique<size_type[]>(std::max(n, m));
  100. const auto sbuk = std::make_unique<size_type[]>(m);
  101. pointer sa = data.get(), rk = sa + n, ht = rk + n;
  102. sais(s, sa, type.get(), rk, ht, lbuk.get(), sbuk.get(), n, m);
  103. for (size_type i = 0; i < n; ++i) rk[sa[i]] = i;
  104. for (size_type k = 0, i = 0; i < n; ++i) {
  105. if (rk[i] == 0) continue;
  106. if (k > 0) --k;
  107. for (size_type j = sa[rk[i] - 1], l = n - std::max(i, j); k < l; ++k)
  108. if (s[i + k] != s[j + k]) break;
  109. ht[rk[i]] = k;
  110. }
  111. this->sa = sa;
  112. this->rk = rk;
  113. this->ht = ht;
  114. }
  115. size_type suffix(size_type p) const { return sa[p]; }
  116. size_type rank(size_type p) const { return rk[p]; }
  117. size_type height(size_type p) const { return ht[p]; }
  118. };
  119. class Solution {
  120. public:
  121. string longestDupSubstring(string s) {
  122. const int n = s.size();
  123. SuffixArray sa(s.c_str(), n, 128);
  124. int len = 0, pos = -1;
  125. for (int i = 1; i < n; ++i) {
  126. if (sa.ht[i] > len) {
  127. len = sa.ht[i];
  128. pos = sa.sa[i];
  129. }
  130. }
  131. return pos == -1 ? "" : s.substr(pos, len);
  132. }
  133. };