#pragma region header
#include <bits/stdc++.h>
#define int long long
#define all(a) begin(a), end(a)
#define rall(a) rbegin(a), rend(a)
#define mp make_pair
#define rep1(i, n) for (decltype(+n) i = 0; i < (n); i++)
#define rrep1(i, n) for (auto i = n - 1; i > static_cast<decltype(i)>(-1); i--)
#define rep2(i, a, b) for (auto i = (a); i < (b); i++)
#define rrep2(i, a, b) for (auto i = b - 1; i >= a; i--)
#define GET_MACRO(_1, _2, _3, NAME, ...) NAME
#define rep(...) GET_MACRO(__VA_ARGS__, rep2, rep1) (__VA_ARGS__)
#define rrep(...) GET_MACRO(__VA_ARGS__, rrep2, rrep1) (__VA_ARGS__)
#define each(i, a) for (auto &&i : (a))
using namespace std;

using ld = long double;
using vi = vector<int>;
using vvi = vector<vi>;
using vs = vector<string>;
using vvs = vector<vs>;
using vd = vector<ld>;
using vvd = vector<vd>;
using vb = vector<bool>;
using vvb = vector<vb>;
using pii = pair<int, int>;
using vp = vector<pii>;
using vvp = vector<vp>;
using mii = map<int, int>;
using vm = vector<mii>;
using vvm = vector<vm>;
template <class T, class U>
using umap = unordered_map<T, U>;
using umii = umap<int, int>;
using seti = set<int>;
template <class T>
using uset = unordered_set<T>;
using useti = uset<int>;
template <class T>
using less_queue = priority_queue<T>;
template <class T>
using greater_queue = priority_queue<T, vector<T>, greater<T>>;
using int128 = __int128_t;

ostream &operator<<(ostream &dest, int128 value) {
  ostream::sentry s(dest);
  if (s) {
    int128 tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(ios_base::badbit);
    }
  }
  return dest;
}

const int INF = 1e18;
const ld EPS = 1e-10;

template <class T>
void SORT(T &a) { stable_sort(all(a)); }
template <class T>
void RSORT(T &a) { stable_sort(rall(a)); }
template <class T>
void rev(T &a) { reverse(all(a)); }
template <class T>
void uniq(T &a) { a.erase(unique(all(a)), end(a)); }
template <class T>
auto min_of(const T &a) { return *min_element(all(a)); }
template <class T>
auto max_of(const T &a) { return *max_element(all(a)); }
template <class T>
T sum_of(const vector<T> &a) { return accumulate(all(a), (T)0); }
template <class T, class U>
int count_of(const T &a, const U &i) { return count(all(a), i); }
template <class T>
bool has(const vector<T> &a, const T &i) { return find(all(a), i) != a.end(); }
bool has(const string &a, const char &i) { return find(all(a), i) != a.end(); }
template <class T>
bool has(const set<T> &a, const T &i) { return a.find(i) != a.end(); }
template <class T, class U>
bool has(const map<T, U> &a, const T &i) { return a.find(i) != a.end(); }
template <class T, class U>
bool has(const umap<T, U> &a, const T &i) { return a.find(i) != a.end(); }
template <class T>
int sz(const T &a) { return a.size(); };

template <class T>
void COUT(const T &x) { cout << x << endl; }
template <class T, class U>
void COUT(const T &x, const U &y) { cout << x << ' ' << y << endl; }
template <class T, class U, class V>
void COUT(const T &x, const U &y, const V &z) { cout << x << ' ' << y << ' ' << z << endl; }
template <class T>
void CSP(const T &x) { cout << x << ' '; }
template <class T>
void CVEC(const T &v) {
  int c = v.size() - 1;
  for (int i = 0; i < c; i++) cout << v[i] << ' ';
  if (c > -1) cout << v[c];
  cout << endl;
}

template <class T>
bool amin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T>
bool amax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

constexpr int lshift(const int &x) noexcept { return 1ll << x; }
constexpr int popcount(const unsigned int &x) noexcept { return __builtin_popcountll(x); }
constexpr int least1(const unsigned int &x) noexcept { return __builtin_ffsll(x); }
constexpr int ceil_div(const int &x, const int &y) noexcept { return (x + y - 1) / y; }

#pragma endregion header

namespace internal {
vector<int> sa_naive(const vector<int> &s) {
  int n = (int)(s.size());
  vector<int> sa(n);
  iota(sa.begin(), sa.end(), 0);
  sort(sa.begin(), sa.end(), [&](int l, int 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;
}
vector<int> sa_doubling(const vector<int> &s) {
  int n = (int)(s.size());
  vector<int> sa(n), rnk = s, tmp(n);
  iota(sa.begin(), sa.end(), 0);
  for (int 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;
    };
    sort(sa.begin(), sa.end(), cmp);
    tmp[sa[0]] = 0;
    for (int i = 1; i < n; i++) tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
    swap(tmp, rnk);
  }
  return sa;
}
template <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40>
vector<int> sa_is(const vector<int> &s, int upper) {
  int n = (int)(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);

  vector<int> sa(n);
  vector<bool> ls(n);
  for (int i = n - 2; i >= 0; i--) ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
  vector<int> sum_l(upper + 1), sum_s(upper + 1);
  for (int i = 0; i < n; i++) {
    if (!ls[i]) sum_s[s[i]]++;
    else sum_l[s[i] + 1]++;
  }
  for (int i = 0; i <= upper; i++) {
    sum_s[i] += sum_l[i];
    if (i < upper) sum_l[i + 1] += sum_s[i];
  }
  auto induce = [&](const vector<int> &lms) {
    fill(sa.begin(), sa.end(), -1);
    vector<int> buf(upper + 1);
    copy(sum_s.begin(), sum_s.end(), buf.begin());
    for (auto d : lms) if (d != n) sa[buf[s[d]]++] = d;
    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;
    }
    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;
    }
  };
  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++;
  vector<int> lms;
  lms.reserve(m);
  for (int i = 1; i < n; i++) if (!ls[i - 1] && ls[i]) lms.push_back(i);
  induce(lms);
  if (m) {
    vector<int> sorted_lms;
    sorted_lms.reserve(m);
    for (int v : sa) if (lms_map[v] != -1) sorted_lms.push_back(v);
    vector<int> rec_s(m);
    int rec_upper = 0;
    rec_s[lms_map[sorted_lms[0]]] = 0;
    for (int i = 1; i < m; i++) {
      int l = sorted_lms[i - 1], r = sorted_lms[i];
      int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
      int 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 && s[l] == s[r]) {
          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 (int i = 0; i < m; i++) sorted_lms[i] = lms[rec_sa[i]];
    induce(sorted_lms);
  }
  return sa;
}
}

vector<int> suffix_array(const vector<int> &s, int upper) {
  assert(0 <= upper);
  for (int d : s) assert(0 <= d && d <= upper);
  auto sa = internal::sa_is(s, upper);
  return sa;
}

template <class T>
vector<int> suffix_array(const vector<T> &s) {
  int n = (int)(s.size());
  vector<int> idx(n);
  iota(idx.begin(), idx.end(), 0);
  sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; });
  vector<int> s2(n);
  int now = 0;
  for (int 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);
}

vector<int> suffix_array(const string &s) {
  int n = (int)(s.size());
  vector<int> s2(n);
  for (int i = 0; i < n; i++) s2[i] = s[i];
  return internal::sa_is(s2, 255);
}

template <class T>
vector<int> lcp_array(const vector<T> &s, const vector<int> &sa) {
  int n = (int)(s.size());
  assert(n >= 1);
  vector<int> rnk(n);
  for (int i = 0; i < n; i++) rnk[sa[i]] = i;
  vector<int> lcp(n - 1);
  int h = 0;
  for (int 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;
}

vector<int> lcp_array(const string &s, const vector<int> &sa) {
  int n = (int)(s.size());
  vector<int> s2(n);
  for (int i = 0; i < n; i++) s2[i] = s[i];
  return lcp_array(s2, sa);
}

void solve(string S) {
  int N = sz(S);
  vi suf = suffix_array(S), lcp = lcp_array(S, suf);
  int ans = N - suf[0];
  rep(i, N - 1) ans += N - suf[i + 1] - lcp[i];
  COUT(ans);
}


#pragma region main
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cout << fixed << setprecision(15);

  string S;
  cin >> S;
  solve(S);
}
#pragma endregion main


Measured memory_bytes: 27984