/* Repetitive String Invention * * Compute an LCP array in O(n^2) time. Use this to count the number of pairs * of equal substrings. * * All other repetitive strings are of the form ABA B or B ABA. Use the LCP * array to find ABA strings, then use prefix sums to count the number of * occurences of B in a prefix or suffix. */ #include #include #include #include #include #include #include constexpr size_t MAXN = 808; int32_t lcp[MAXN][MAXN]; int32_t psum[MAXN][MAXN]; std::vector byVal[MAXN]; int main() { std::string s; std::cin >> s; size_t n = s.size(); std::memset(lcp, 0, sizeof(lcp)); for (size_t i = n - 1; i < n; --i) { for (size_t j = n - 1; j < n; --j) { if (s[i] == s[j]) { lcp[i][j] = 1 + lcp[i + 1][j + 1]; } } } for (size_t i = 0; i < n; ++i) { for (size_t j = i + 1; j < n; ++j) { lcp[j][i] = lcp[i][j]; } } for (size_t i = 0; i < n; ++i) { for (size_t j = i + 1; j < n; ++j) { byVal[lcp[i][j]].push_back(n * i + j); } } int64_t ans = 0; for (size_t i = 0; i < n; ++i) { for (size_t j = i + 1; j < n; ++j) { ans += std::min(j - i, lcp[i][j]); } } std::memset(psum, 0, sizeof(psum)); for (size_t len2 = n - 1; len2 > 0; --len2) { for (int32_t ij : byVal[len2]) { int32_t i = ij / n; int32_t j = ij % n; for (auto k = j; k <= n; ++k) { ++psum[i][k]; } for (auto k = i; k <= n; ++k) { ++psum[j][k]; } } for (size_t len1 = 1; 2 * len1 + len2 <= n; ++len1) { for (size_t i = 0, j = 2 * len1 + len2; j <= n; ++i, ++j) { if (lcp[i][j - len1] >= len1) { // add a[i][k] over all k where // k + len2 <= i if (i >= len2) { ans += psum[i + len1][i - len2]; } // k >= j if (j + len2 <= n) { ans += psum[i + len1][n] - psum[i + len1][j - 1]; } } } } } std::cout << ans << '\n'; return 0; }