Language: C++

#pragma GCC optimize("Ofast")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx")
#include <bits/stdc++.h>
#ifndef ATCODER_STRING_HPP
#define ATCODER_STRING_HPP 1
#include <algorithm>
#include <cassert>
#include <numeric>
#include <string>
#include <vector>
#define ui unsigned int
#define ul unsigned long
namespace atcoder
{
    namespace internal
    {
        std::vector<ui> sa_naive(const std::vector<ui> &s)
        {
            ui n = s.size();
            std::vector<ui> sa(n);
            std::iota(sa.begin(), sa.end(), 0);
            std::sort(sa.begin(), sa.end(), [&](ui l, ui r) {
                if (l == r)
                    return false;
                while (l < n && r < n)
                {
                    if (s[l] != s[r])
                        return s[l] < s[r];
                    l++;
                    r++;
                }
                return l == n;
            });
            return sa;
        }
        std::vector<ui> sa_doubling(const std::vector<ui> &s)
        {
            ui n = s.size();
            std::vector<int> sa(n), rnk = s, tmp(n);
            std::iota(sa.begin(), sa.end(), 0);
            for (ui k = 1; k < n; k *= 2)
            {
                auto cmp = [&](int x, int y) {
                    if (rnk[x] != rnk[y])
                        return rnk[x] < rnk[y];
                    int rx = x + k < n ? rnk[x + k] : -1;
                    int ry = y + k < n ? rnk[y + k] : -1;
                    return rx < ry;
                };
                std::sort(sa.begin(), sa.end(), cmp);
                tmp[sa[0]] = 0;
                for (ui i = 1; i < n; i++)
                {
                    tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
                }
                std::swap(tmp, rnk);
            }
            return sa;
        }
        // SA-IS, linear-time suffix array construction
        // Reference:
        // G. Nong, S. Zhang, and W. H. Chan,
        // Two Efficient Algorithms for Linear Time Suffix Array Construction
        template <constexpr ui THRESHOLD_NAIVE = 10, constexpr ui THRESHOLD_DOUBLING = 40>
        std::vector<ui> sa_is(const std::vector<ui> &s, ui upper)
        {
            ui n = s.size();
            if (n == 0)
                return {};
            if (n == 1)
                return {0};
            if (n == 2)
            {
                if (s[0] < s[1])
                {
                    return {0, 1};
                }
                else
                {
                    return {1, 0};
                }
            }
            if (n < THRESHOLD_NAIVE)
            {
                return sa_naive(s);
            }
            if (n < THRESHOLD_DOUBLING)
            {
                return sa_doubling(s);
            }
            std::vector<int> sa(n);
            std::vector<bool> ls(n);
            for (ui i = n - 2; i >= 0; i--)
            {
                ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
            }
            std::vector<ui> sum_l(upper + 1), sum_s(upper + 1);
            for (ui i = 0; i < n; i++)
            {
                if (!ls[i])
                {
                    sum_s[s[i]]++;
                }
                else
                {
                    sum_l[s[i] + 1]++;
                }
            }
            for (ui i = 0; i <= upper; i++)
            {
                sum_s[i] += sum_l[i];
                if (i < upper)
                    sum_l[i + 1] += sum_s[i];
            }
            auto induce = [&](const std::vector<ui> &lms) {
                std::fill(sa.begin(), sa.end(), -1);
                std::vector<int> buf(upper + 1);
                std::copy(sum_s.begin(), sum_s.end(), buf.begin());
                for (auto d : lms)
                {
                    if (d == n)
                        continue;
                    sa[buf[s[d]]++] = d;
                }
                std::copy(sum_l.begin(), sum_l.end(), buf.begin());
                sa[buf[s[n - 1]]++] = n - 1;
                for (int i = 0; i < n; i++)
                {
                    int v = sa[i];
                    if (v >= 1 && !ls[v - 1])
                    {
                        sa[buf[s[v - 1]]++] = v - 1;
                    }
                }
                std::copy(sum_l.begin(), sum_l.end(), buf.begin());
                for (int i = n - 1; i >= 0; i--)
                {
                    int v = sa[i];
                    if (v >= 1 && ls[v - 1])
                    {
                        sa[--buf[s[v - 1] + 1]] = v - 1;
                    }
                }
            };
            std::vector<int> lms_map(n + 1, -1);
            int m = 0;
            for (int i = 1; i < n; i++)
            {
                if (!ls[i - 1] && ls[i])
                {
                    lms_map[i] = m++;
                }
            }
            std::vector<int> lms;
            lms.reserve(m);
            for (int i = 1; i < n; i++)
            {
                if (!ls[i - 1] && ls[i])
                {
                    lms.emplace_back(i);
                }
            }
            induce(lms);
            if (m)
            {
                std::vector<ui> sorted_lms;
                sorted_lms.reserve(m);
                for (int v : sa)
                {
                    if (lms_map[v] != -1)
                        sorted_lms.push_back(v);
                }
                std::vector<int> rec_s(m);
                int rec_upper = 0;
                rec_s[lms_map[sorted_lms[0]]] = 0;
                for (ui i = 1; i < m; i++)
                {
                    ui l = sorted_lms[i - 1], r = sorted_lms[i];
                    ui end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
                    ui end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;
                    bool same = true;
                    if (end_l - l != end_r - r)
                    {
                        same = false;
                    }
                    else
                    {
                        while (l < end_l)
                        {
                            if (s[l] != s[r])
                            {
                                break;
                            }
                            l++;
                            r++;
                        }
                        if (l == n || s[l] != s[r])
                            same = false;
                    }
                    if (!same)
                        rec_upper++;
                    rec_s[lms_map[sorted_lms[i]]] = rec_upper;
                }
                auto rec_sa =
                    sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);
                for (ui i = 0; i < m; i++)
                {
                    sorted_lms[i] = lms[rec_sa[i]];
                }
                induce(sorted_lms);
            }
            return sa;
        }
    } // namespace internal
    std::vector<ui> suffix_array(const std::vector<ui> &s, ui upper)
    {
        assert(0 <= upper);
        for (ui d : s)
        {
            assert(0 <= d && d <= upper);
        }
        auto sa = internal::sa_is(s, upper);
        return sa;
    }
    template <class T>
    std::vector<ui> suffix_array(const std::vector<T> &s)
    {
        ui n = s.size();
        std::vector<int> idx(n);
        iota(idx.begin(), idx.end(), 0);
        sort(idx.begin(), idx.end(), [&](ui l, ui r) { return s[l] < s[r]; });
        std::vector<int> s2(n);
        ui now = 0;
        for (ui i = 0; i < n; i++)
        {
            if (i && s[idx[i - 1]] != s[idx[i]])
                now++;
            s2[idx[i]] = now;
        }
        return internal::sa_is(s2, now);
    }
    std::vector<int> suffix_array(const std::string &s)
    {
        int n = int(s.size());
        std::vector<int> s2(n);
        for (int i = 0; i < n; i++)
        {
            s2[i] = s[i];
        }
        return internal::sa_is(s2, 255);
    }
    // Reference:
    // T. Kasai, G. Lee, H. Arimura, S. Arikawa, and K. Park,
    // Linear-Time Longest-Common-Prefix Computation in Suffix Arrays and Its
    // Applications
    template <class T>
    std::vector<ui> lcp_array(const std::vector<T> &s,
                               const std::vector<ui> &sa)
    {
        ui n = s.size();
        assert(n >= 1);
        std::vector<ui> rnk(n);
        for (ui i = 0; i < n; i++)
        {
            rnk[sa[i]] = i;
        }
        std::vector<ui> lcp(n - 1);
        ui h = 0;
        for (ui i = 0; i < n; i++)
        {
            if (h > 0)
                h--;
            if (rnk[i] == 0)
                continue;
            int j = sa[rnk[i] - 1];
            for (; j + h < n && i + h < n; h++)
            {
                if (s[j + h] != s[i + h])
                    break;
            }
            lcp[rnk[i] - 1] = h;
        }
        return lcp;
    }
    std::vector<int> lcp_array(const std::string &s, const std::vector<ui> &sa)
    {
        ui n = s.size();
        std::vector<ui> s2(n);
        for (ui i = 0; i < n; i++)
        {
            s2[i] = s[i];
        }
        return lcp_array(s2, sa);
    }
    // Reference:
    // D. Gusfield,
    // Algorithms on Strings, Trees, and Sequences: Computer Science and
    // Computational Biology
    template <class T>
    std::vector<int> z_algorithm(const std::vector<T> &s)
    {
        int n = int(s.size());
        if (n == 0)
            return {};
        std::vector<int> z(n);
        z[0] = 0;
        for (int i = 1, j = 0; i < n; i++)
        {
            int &k = z[i];
            k = (j + z[j] <= i) ? 0 : std::min(j + z[j] - i, z[i - j]);
            while (i + k < n && s[k] == s[i + k])
                k++;
            if (j + z[j] < i + z[i])
                j = i;
        }
        z[0] = n;
        return z;
    }
    std::vector<int> z_algorithm(const std::string &s)
    {
        int n = int(s.size());
        std::vector<int> s2(n);
        for (int i = 0; i < n; i++)
        {
            s2[i] = s[i];
        }
        return z_algorithm(s2);
    }
} // namespace atcoder
#endif // ATCODER_STRING_HPP
#define _GLIBCXX_DEBUG
using namespace std;
using namespace atcoder;
#define loop(i, n) for (ui i = 0; i < n; i++)
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    string S;
    cin >> S;
    vector<int> la = lcp_array(S, suffix_array(S));
    ul ans = S.size() * (S.size() + 1) / 2;
    loop(i, la.size()) ans -= la[i];
    cout << ans << ' ';
    return 0;
}


Compiler output:
a.cc: In function 'std::vector<unsigned int> atcoder::internal::sa_doubling(const std::vector<unsigned int>&)':
a.cc:41:43: error: conversion from 'vector<unsigned int>' to non-scalar type 'vector<int>' requested
   41 |             std::vector<int> sa(n), rnk = s, tmp(n);
      |                                           ^
a.cc:60:20: error: could not convert 'sa' from 'vector<int>' to 'vector<unsigned int>'
   60 |             return sa;
      |                    ^~
      |                    |
      |                    vector<int>
a.cc: At global scope:
a.cc:66:19: error: a parameter cannot be declared 'constexpr'
   66 |         template <constexpr ui THRESHOLD_NAIVE = 10, constexpr ui THRESHOLD_DOUBLING = 40>
      |                   ^~~~~~~~~
a.cc:66:54: error: a parameter cannot be declared 'constexpr'
   66 |         template <constexpr ui THRESHOLD_NAIVE = 10, constexpr ui THRESHOLD_DOUBLING = 40>
      |                                                      ^~~~~~~~~
a.cc: In function 'std::vector<unsigned int> atcoder::internal::sa_is(const std::vector<unsigned int>&, unsigned int)':
a.cc:214:20: error: could not convert 'static_cast<std::vector<int>&&>(sa)' from 'vector<int>' to 'vector<unsigned int>'
  214 |             return sa;
      |                    ^~
      |                    |
      |                    vector<int>
a.cc: In function 'std::vector<unsigned int> atcoder::suffix_array(const std::vector<_Tp>&)':
a.cc:242:31: error: no matching function for call to 'sa_is(std::vector<int>&, unsigned int&)'
  242 |         return internal::sa_is(s2, now);
      |                ~~~~~~~~~~~~~~~^~~~~~~~~
a.cc:67:25: note: candidate: 'template<unsigned int THRESHOLD_NAIVE, unsigned int THRESHOLD_DOUBLING> std::vector<unsigned int> atcoder::internal::sa_is(const std::vector<unsigned int>&, unsigned int)'
   67 |         std::vector<ui> sa_is(const std::vector<ui> &s, ui upper)
      |                         ^~~~~
a.cc:67:25: note:   template argument deduction/substitution failed:
a.cc:242:32: note:   cannot convert 's2' (type 'std::vector<int>') to type 'const std::vector<unsigned int>&'
  242 |         return internal::sa_is(s2, now);
      |                                ^~
a.cc: In function 'std::vector<int> atcoder::suffix_array(const std::string&)':
a.cc:252:31: error: no matching function for call to 'sa_is(std::vector<int>&, int)'
  252 |         return internal::sa_is(s2, 255);
      |                ~~~~~~~~~~~~~~~^~~~~~~~~
a.cc:67:25: note: candidate: 'template<unsigned int THRESHOLD_NAIVE, unsigned int THRESHOLD_DOUBLING> std::vector<unsigned int> atcoder::internal::sa_is(const std::vector<unsigned int>&, unsigned int)'
   67 |         std::vector<ui> sa_is(const std::vector<ui> &s, ui upper)
      |                         ^~~~~
a.cc:67:25: note:   template argument deduction/substitution failed:
a.cc:252:32: note:   cannot convert 's2' (type 'std::vector<int>') to type 'const std::vector<unsigned int>&'
  252 |         return internal::sa_is(s2, 255);
      |                                ^~
a.cc: In function 'std::vector<int> atcoder::lcp_array(const std::string&, const std::vector<unsigned int>&)':
a.cc:295:25: error: could not convert 'atcoder::lcp_array(const std::vector<_Tp>&, const std::vector<unsigned int>&) [with T = unsigned int]((* & sa))' from 'vector<unsigned int>' to 'vector<int>'
  295 |         return lcp_array(s2, sa);
      |                ~~~~~~~~~^~~~~~~~
      |                         |
      |                         vector<unsigned int>
a.cc: In function 'int main()':
a.cc:343:31: error: no matching function for call to 'lcp_array(std::string&, std::vector<int>)'
  343 |     vector<int> la = lcp_array(S, suffix_array(S));
      |                      ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
a.cc:259:21: note: candidate: 'template<class T> std::vector<unsigned int> atcoder::lcp_array(const std::vector<_Tp>&, const std::vector<unsigned int>&)'
  259 |     std::vector<ui> lcp_array(const std::vector<T> &s,
      |                     ^~~~~~~~~
a.cc:259:21: note:   template argument deduction/substitution failed:
a.cc:343:31: note:   'std::string' {aka 'std::__cxx11::basic_string<char>'} is not derived from 'const std::vector<_Tp>'
  343 |     vector<int> la = lcp_array(S, suffix_array(S));
      |                      ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
a.cc:287:22: note: candidate: 'std::vector<int> atcoder::lcp_array(const std::string&, const std::vector<unsigned int>&)'
  287 |     std::vector<int> lcp_array(const std::string &s, const std::vector<ui> &sa)
      |                      ^~~~~~~~~
a.cc:287:77: note:   no known conversion for argument 2 from 'std::vector<int>' to 'const std::vector<unsigned int>&'
  287 |     std::vector<int> lcp_array(const std::string &s, const std::vector<ui> &sa)
      |                                                      ~~~~~~~~~~~~~~~~~~~~~~~^~
a.cc: In instantiation of 'std::vector<unsigned int> atcoder::internal::sa_is(const std::vector<unsigned int>&, unsigned int) [with unsigned int THRESHOLD_NAIVE = 10; unsigned int THRESHOLD_DOUBLING = 40]':
a.cc:224:34:   required from here
  224 |         auto sa = internal::sa_is(s, upper);
      |                   ~~~~~~~~~~~~~~~^~~~~~~~~~
a.cc:165:19: error: no match for call to '(atcoder::internal::sa_is<>(const std::vector<unsigned int>&, unsigned int)::<lambda(const std::vector<unsigned int>&)>) (std::vector<int>&)'
  165 |             induce(lms);
      |             ~~~~~~^~~~~
a.cc:117:27: note: candidate: 'atcoder::internal::sa_is<>(const std::vector<unsigned int>&, unsigned int)::<lambda(const std::vector<unsigned int>&)>'
  117 |             auto induce = [&](const std::vector<ui> &lms) {
      |                           ^
a.cc:117:27: note:   no known conversion for argument 1 from 'std::vector<int>' to 'const std::vector<unsigned int>&'
a.cc:207:64: error: invalid initialization of reference of type 'const std::vector<unsigned int>&' from expression of type 'std::vector<int>'
  207 |                     sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);
      |                                                                ^~~~~
a.cc:67:54: note: in passing argument 1 of 'std::vector<unsigned int> atcoder::internal::sa_is(const std::vector<unsigned int>&, unsigned int) [with unsigned int THRESHOLD_NAIVE = 10; unsigned int THRESHOLD_DOUBLING = 40]'
   67 |         std::vector<ui> sa_is(const std::vector<ui> &s, ui upper)
      |                               ~~~~~~~~~~~~~~~~~~~~~~~^