cplib-cpp

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub hitonanode/cplib-cpp

:heavy_check_mark: string/test/lcp.test.cpp

Depends on

Code

#include "../suffix_array_doubling.hpp"
#define PROBLEM "https://judge.yosupo.jp/problem/number_of_substrings"
#include <iostream>
#include <string>

int main() {
    std::string S;
    std::cin >> S;
    SuffixArray<decltype(S)> sa(S, true);

    long long ret = (long long)S.length() * (S.length() + 1) / 2;
    std::cout << ret - std::accumulate(sa.lcp.begin(), sa.lcp.end(), 0LL) << '\n';
}
#line 2 "string/suffix_array_doubling.hpp"
#include <algorithm>
#include <numeric>
#include <vector>

// CUT begin
// Suffix Array / Longest Common Prefix Array Construction
// Comlexity: O(N(log N)^2)
template <typename T> struct [[deprecated("use ACL based suffix array")]] SuffixArray {
    T S;                   // size: N
    std::vector<int> SA;   // Suffix Array (size: N + 1, SA[0] == N) SA[i] means S[SA[i]:]
    std::vector<int> rank; // Rank (inverse of SA) (size: N + 1, rank[N] == 0)
    std::vector<int> lcp;  // Longest Common Prefix Array (size: N) betw. S[SA[i]:] & S[SA[i + 1]:]

    SuffixArray(const T &str, bool gen_lcp = true) : S(str) {
        int N = S.size();
        SA.resize(N + 1);
        std::iota(SA.begin(), SA.end(), 0);
        rank.assign(N + 1, -1);
        for (int i = 0; i < N; i++) rank[i] = S[i];
        int _ord_mm = 1;

        auto _comp_suffarr = [&](int i, int j) {
            if (rank[i] != rank[j]) return rank[i] < rank[j];
            int ri = i + _ord_mm < (int)rank.size() ? rank[i + _ord_mm] : -1;
            int rj = j + _ord_mm < (int)rank.size() ? rank[j + _ord_mm] : -1;
            return ri < rj;
        };
        std::vector<int> tmp(N + 1);
        for (_ord_mm = 1; _ord_mm <= N; _ord_mm *= 2) {
            std::sort(SA.begin(), SA.end(), _comp_suffarr);
            tmp[SA[0]] = 0;
            for (int i = 1; i <= N; i++) {
                tmp[SA[i]] = tmp[SA[i - 1]] + _comp_suffarr(SA[i - 1], SA[i]);
            }
            rank = tmp;
        }
        if (!gen_lcp) return;

        lcp.assign(N, 0);
        int h = 0;
        for (int i = 0; i < N; i++) {
            int j = SA[rank[i] - 1];
            if (h) h--;
            for (; j + h < N and i + h < N; h++)
                if (S[j + h] != S[i + h]) break;
            lcp[rank[i] - 1] = h;
        }
    }
};
#line 2 "string/test/lcp.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/number_of_substrings"
#include <iostream>
#include <string>

int main() {
    std::string S;
    std::cin >> S;
    SuffixArray<decltype(S)> sa(S, true);

    long long ret = (long long)S.length() * (S.length() + 1) / 2;
    std::cout << ret - std::accumulate(sa.lcp.begin(), sa.lcp.end(), 0LL) << '\n';
}
Back to top page