#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <set>
#include <queue>
#include <stack>
#include <tuple>
#include <cmath>
#include <iomanip>
#include <map>
#include <cstring>
#include <functional>
#include <cctype>
#include <locale>
#include <numeric>
#include <array>
#define ll long long
#define rep(i,n) for(int i=0;i<(n);i++)
#define rrep(i,n) for(int i=n-1;i>=0;i--)
#define fi first
#define se second
#define pb push_back
#define ALL(a) (a).begin(),(a).end()
using namespace std;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}
typedef pair<int,int> P;
typedef pair<long long,long long> Pll;
#define fout(num) cout << fixed << setprecision(20) << (num) << endl
//s[i]=tolower(s[i]); islower(s[i]); cout << tolower(s[i])はバグ
//vector<vector<ll>> dp(n,vector<ll>(n))
//2-dim:vector<vector<Type>> vv(n, vector<Type>(m, d));
//3-dim:vector<vector<vector<Type>>> vvv(n, vector<vector<Type>>(m, vector<Type>(l, d)));

template<typename T>
struct RollingHash{
    static const long long base1=1007LL,base2=2009LL;
    static const long long MOD1=1000000007LL,MOD2=1000000009LL;
    vector<long long> hash1,hash2,pow1,pow2;
    RollingHash(const T &s){
        int sz=(int)s.size();
        hash1.assign(sz+1,0); hash2.assign(sz+1,0);
        pow1.assign(sz+1,1); pow2.assign(sz+1,1);
        for(int i=0;i<sz;i++){
            hash1[i+1]=(hash1[i]*base1+s[i]) % MOD1;
            hash2[i+1]=(hash2[i]*base2+s[i]) % MOD2;
            pow1[i+1]=(pow1[i]*base1) % MOD1;
            pow2[i+1]=(pow2[i]*base2) % MOD2;
        }
    }
    inline pair<long long,long long> query(int l,int r)const{
        if(l<0||r>=hash1.size()||r-l<0) return {0,0};
        long long ret1=hash1[r]-hash1[l]*pow1[r-l]%MOD1;
        ret1=(ret1+MOD1)%MOD1;
        long long ret2=hash2[r]-hash2[l]*pow2[r-l]%MOD2;
        ret2=(ret2+MOD2)%MOD2;
        return {ret1,ret2};
    }
    inline int lcp(int a,int b)const{
        int len=min((int)hash1.size()-a,(int)hash1.size()-b);
        int ok=0,ng=len+1;
        while(ng-ok>1){
            int mid=(ng+ok)>>1;
            if(query(a,a+mid)==query(b,b+mid)) ok=mid;
            else ng=mid;
        }
        return ok;
    }
    inline int lcp(const RollingHash &t,int a,int b)const{
        int len=min((int)hash1.size()-a,(int)hash1.size()-b);
        int ok=0,ng=len+1;
        while(ng-ok>1){
            int mid=(ng+ok)>>1;
            if(query(a,a+mid)==t.query(b,b+mid)) ok=mid;
            else ng=mid;
        }
        return ok;
    }
};
template<typename T>
struct SA{
    T s;
    vector<int> sa,rsa,lcp;
    SA(){}
    SA(T _s,vector<int> _sa):s(_s),sa(_sa){
        int sz=(int)s.size();
        rsa=vector<int>(sz+1);
        for(int i=0;i<=sz;i++) rsa[sa[i]]=i;
        lcp=vector<int>(sz);
        int h=0;
        for(int i=0;i<sz;i++){
            int j=sa[rsa[i]-1];
            if(h>0) h--;
            for(;j+h<sz&&i+h<sz;h++){
                if(s[j+h]!=s[i+h]) break;
            }
            lcp[rsa[i]-1]=h;
        }
    }
};
template<typename T>
vector<int> SA_IS(T s,int upper=200){
    int sz=(int)s.size();
    vector<int> sa(sz+1);
    if(sz==0) return sa;
    for(int i=0;i<sz;i++) s[i]++;
    s.push_back(0);
    upper++;
    vector<bool> ls(sz+1);
    ls[sz]=true;
    for(int i=sz-1;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<=sz;i++){
        if (!ls[i]) sum_s[s[i]]++;
        else sum_l[s[i]+1]++;
    }
    for(int i=0;i<upper;i++){
        sum_l[i+1] += sum_s[i];
        sum_s[i+1] += sum_l[i+1];
    }
    auto induce=[&](const vector<int> &lms){
        fill(begin(sa),end(sa),-1);
        auto buf0=sum_s;
        for (auto d:lms) sa[buf0[s[d]]++] = d;
        auto buf1=sum_l;
        for(int i=0;i<=sz;i++){
            int v=sa[i];
            if(v>=1 && !ls[v-1]) sa[buf1[s[v-1]]++]=v-1;
        }
        auto buf2=sum_l;
        for(int i=sz;i>=0;i--){
            int v=sa[i];
            if(v>=1 && ls[v-1]) sa[--buf2[s[v-1]+1]] = v-1;
        }
    };
    vector<int> lms,lms_map(sz+1,-1);
    for(int i=1;i<=sz;i++){
        if(!ls[i-1] && ls[i]){
            lms_map[i]=(int)lms.size();
            lms.push_back(i);
        }
    }
    induce(lms);
    if (lms.size()>=2) {
        int m=(int)lms.size()-1;
        vector<int> lms2;
        for (int v:sa) {
            if(lms_map[v]!=-1) lms2.push_back(v);
        }
        int rec_n=1;
        vector<int> rec_s(m);
        rec_s[lms_map[lms2[1]]] = 1;
        for(int i=2;i<=m;i++){
            int l=lms2[i-1],r=lms2[i];
            int nl=lms[lms_map[l]+1], nr=lms[lms_map[r]+1];
            if (nl-l!=nr-r) rec_n++;
            else{
                while(l<=nl){
                    if(s[l]!=s[r]){
                        rec_n++;
                        break;
                    }
                    l++; r++;
                }
            }
            rec_s[lms_map[lms2[i]]] = rec_n;
        }
        vector<int> nx_lms;
        auto ch_sa = SA_IS(rec_s,rec_n);
        for(int d:ch_sa) nx_lms.push_back(lms[d]);
        induce(nx_lms);
    }
    return sa;
};

signed main(){
    std::cin.tie(nullptr);
    std::ios_base::sync_with_stdio(false);
    string s; cin >> s;
    ll n=(ll)s.size();
    SA<string> sa(s,SA_IS(s));
    RollingHash<string> rh(s);
    ll ans=n*(n+1LL)/2LL;
    rep(i,n-1){
        //cout << sa.sa[i+1] << endl;
        ll res=rh.lcp(sa.sa[i+1],sa.sa[i+2]);
        ans-=res;
    }
    cout << ans << endl;
}


Measured memory_bytes: 29296