#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;

#define INF_LL (int64)1e18
#define INF (int32)1e9
#define REP(i, n) for(int64 i = 0;i < (n);i++)
#define FOR(i, a, b) for(int64 i = (a);i < (b);i++)
#define all(x) x.begin(),x.end()
#define fs first
#define sc second

using int32 = int_fast32_t;
using uint32 = uint_fast32_t;
using int64 = int_fast64_t;
using uint64 = uint_fast64_t;
using PII = pair<int32, int32>;
using PLL = pair<int64, int64>;

const double eps = 1e-10;

template<typename A, typename B>inline void chmin(A &a, B b){if(a > b) a = b;}
template<typename A, typename B>inline void chmax(A &a, B b){if(a < b) a = b;}

template<typename T>
vector<T> make_v(size_t a){return vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
	return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

template<typename T,typename U,typename... V>
typename enable_if<is_same<T, U>::value!=0>::type
fill_v(U &u,const V... v){u=U(v...);}

template<typename T,typename U,typename... V>
typename enable_if<is_same<T, U>::value==0>::type
fill_v(U &u,const V... v){
	for(auto &e:u) fill_v<T>(e,v...);
}

using Mint = modint998244353;


template<int NODE_NUM=1000000>
class SuffixAutomaton {
  using value_structure = std::string;
  using value_type = char;
  using size_type = std::int32_t;

  struct Node {
    size_type link, len, pre, original;
    value_type key;
    std::map<value_type, size_type> next;
    Node(value_type key=-1, size_type len=0, size_type link=-1, size_type original=-1)
      : key(key), link(link), len(len), pre(1), original(original) {}

    void dump() {
      std::cout << "(key, len, link, pre cnt): (" << key << ", " << len << ", " << link << ", " << pre << ")" << std::endl;
      for (auto&& u : next) {
        std::cout << "(char, id): (" << u.first << ", " << u.second << ")" << std::endl;
      }
    }
  };

private:
  size_type last, len;

public:
  std::vector<Node> node;

  SuffixAutomaton(): last(0) {
    node.reserve(NODE_NUM);
    node.push_back(Node());
  }

  SuffixAutomaton(const value_structure& s): SuffixAutomaton() {
    extend_by_string(s);
  }

  void extend(const value_type c, size_type base=-1) {
    if (base >= 0) last = base;
    size_type cur, p = last;
    if (node[last].next.count(c) == 0) {
      node.push_back(Node(c, node[last].len + 1));
      cur = node.size() - 1;
    } else {
      cur = node[last].next[c];
    }
    last = cur;

    for (; p != -1 && node[p].next.count(c) == 0; p = node[p].link) node[p].next[c] = cur;

    if (p == -1) {
      node[cur].link = 0;
    } else {
      size_type q = node[p].next[c];
      if (node[p].len + 1 == node[q].len) {
        if (q != cur)
          node[cur].link = q;
        else
          node[cur].pre++;
      } else {
        size_type clone = node.size();
        node.push_back(node[q]);
        node[clone].len = node[p].len + 1;
        node[clone].original = q;

        node[clone].pre = (q == cur); // 新しい文字列を追加する際にcloneが必要になることがあるが、このときはprefixになっている
        if (q == cur) last = clone;

        for (; p != -1 && node[p].next[c] == q; p = node[p].link) node[p].next[c] = clone;
        node[q].link = node[cur].link = clone;
      }
    }
  }

  void extend_by_string(const value_structure& s, size_type base=-1) {
    for (int i = 0; i < s.size(); i++) {
      extend(s[i], (i == 0 ? base : -1));
    }
  }

  void topological_sort() {
    std::vector<size_type> indeg(node.size(), 0), ord(node.size());
    std::vector<Node> node2(node.size());
    size_type p = 1;

    for (auto&& v : node) {
      for (auto&& u : v.next) {
        indeg[u.second]++;
      }
    }
    node2[0] = node[0]; ord[0] = 0;
    for (int i = 0; i < node.size(); i++) {
      for (auto &&u : node2[i].next) {
        if (--indeg[u.second] == 0) {
          ord[u.second] = p;
          node2[p++] = node[u.second];
        }
      }
    }

    for (auto &&v : node2) {
      v.link = v.link == -1 ? -1 : ord[v.link];
      v.original = ord[v.original];
      for (auto &&u : v.next) {
        u.second = ord[u.second];
      }
    }
    swap(node, node2);
  }

  Node& operator[](size_type k) {
    return node[k];
  }

  const size_type size() {
    return node.size();
  }

  void dump() {
    std::cout << "---------------------------------------------------------" << std::endl;
    for (int i = 0; i < node.size(); i++) {
      std::cout << "id: " << i << std::endl;
      node[i].dump();
    }
    std::cout << "---------------------------------------------------------" << std::endl;
  }
};


int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  string S;
  cin >> S;
  SuffixAutomaton<> sa(S);
  vector<int64> dp(sa.size(), 0);
  dp[0] = 1;
  sa.topological_sort();
  int64 res = 0;
  REP(i, dp.size()) {
    for (auto& u : sa[i].next) {
      dp[u.sc] += dp[i];
    }
    res += dp[i];
  }
  cout << res-1 << endl;
}



Measured memory_bytes: 213000