#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define M 100005

int rank[M],sa[M],X[M],Y[M],high[M],init[M];
int buc[M];

inline bool equ(int *r,int a,int b,int l) {return (r[a]==r[b]&&r[a+l]==r[b+l]);}
inline void rsort(int *x, int *y, int n, int m){
	for(int i=0; i<m; i++) buc[i] = 0;
	for(int i=0; i<n; i++) buc[ x[y[i]] ] ++;
	for(int i=1; i<m; i++) buc[i] += buc[i-1];
	for(int i=n-1; i>=0; i--) sa[ --buc[ x[y[i]] ] ] = y[i];
}

void suffix(int n, int m = 128) {
	int *x = X, *y = Y;
	for(int i=0;i<n;i++) x[i] = init[y[i]=i];
	rsort(x, y, n, m);
	int l = 1;
	do{
		int v = 0, p = 1;
		for(int i=n-l; i<n; i++) y[v++] = i;
		for(int i=0; i<n; i++) if(sa[i] >= l) y[v++] = sa[i] - l;
		rsort(x, y, n, m);
		swap(x, y); x[sa[0]] = 0;
		for(int i=1; i<n; i++) x[ sa[i] ] = equ(y,sa[i-1],sa[i],l) ? p-1 : p++;
		l <<= 1; m = p;
	} while( m < n );

	for(int i=1; i<n; i++) rank[sa[i]] = i;
	int k = 0;
	for(int i=0; i<n-1; i++) {
		if(k) k--;
		for(int j = sa[rank[i]-1] ; init[i+k] == init[j+k] ; k++);
		high[rank[i]]=k;
	}
}

char s[M];
int n;

int stk[M], top;
int main() {
	scanf("%s", s);
	int n = strlen(s);
//	s[n] = '~';
//	s[++n] = 0;
	for(int i=0;i<=n;i++) init[i] = s[i];
	suffix(n+1);

//	for(int i=1;i<=n;i++){
//		printf("%d %d\t%s\n", high[i], sa[i], s+sa[i]);
//	}

	LL ans=0, uone=0;
	stk[top=0] = high[1];
	for(int i=2;i<=n;i++){
		int mlen = high[i];
		while(top>=0&&high[stk[top]]>high[i]){
			//printf("~~ %d:%d %d:%d\n", i, high[i], stk[top], high[stk[top]]);
			LL len = high[stk[top]] - max(high[stk[top-1]], high[i]);
			LL a = i-stk[top]+1;
			LL cnt = len*(a*(a+1)/2);
			//printf("?? %I64d %I64d\n", a, len);
			ans+=cnt;
			uone+=a*len;
			top--;
		}
		if(high[i]!=high[stk[top]]) stk[++top] = i;
//		printf("stk:: ");
//		for(int j=0;j<=top;j++){
//			printf("%d ", high[stk[j]]);
//		}puts("");
	}
	for(int i=1;i<=top;i++){
		LL len = high[stk[i]] - high[stk[i-1]];
		LL a = n-stk[i]+2;
		LL cnt = len*(a*(a+1)/2);
		//printf("!! %I64d %I64d\n", a, len);
		ans+=cnt;
		uone+=a*len;
	}
	printf("%I64d\n", ans+(n*(n+1)/2)-uone);
}


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<set>
#include<map>
#include<utility>
#include<vector>
#include<string>
#include<stack>
#include<queue>
using namespace std;
#define MAXLEN 1006
struct State
{
    int len, link;
    map < char , int > nxtc;
} SA[2*MAXLEN];
int FirstPos[2*MAXLEN], DistSub[2*MAXLEN], NumOcc[2*MAXLEN];
bool vis[2*MAXLEN];
char str[MAXLEN];
vector < pair < int , int > > lenState;
__int64 f(int n)
{
    __int64 ret = n;
    ret *= (n+1);
    return ret/2;
}
class SuffixAutomata
{
    int sz, last;
    void init(int idx)
    {
        SA[idx].len = 0, SA[idx].link = -1;
        FirstPos[idx] = -1;
        SA[idx].nxtc.clear();
    }
    bool traverse(int cur, char *ch)
    {
        if (*ch == 0)
        {
            printf("first occurance lasts at = %d :: total # of occurances = %d :: node = %d\nlink = %d :: len = %d\n", FirstPos[cur], NumOcc[cur], cur, SA[cur].link, SA[cur].len);
            return true;
        }
        if (SA[cur].nxtc.count(*ch) == 0) return false;
        int p = SA[cur].nxtc[*ch];
        return traverse(p, ++ch);
    }
    int distSubs(int cur)
    {
        if (vis[cur]) return DistSub[cur];
        vis[cur] = true;
        if (cur) DistSub[cur] = 1;
        else DistSub[cur] = 0;
        map < char , int > :: iterator im;
        map < char , int > &M = SA[cur].nxtc;
        for (im = M.begin(); im != M.end(); ++im) DistSub[cur] += distSubs(im->second);
        return DistSub[cur];
    }
public:
    SuffixAutomata()
    {
        sz = last = 0;
        init(0);
        lenState.clear();
        ++sz;
    }
    int size() {return sz;}
    void extend(char ch)
    {
        int p, q, clone, cur = sz++;
        init(cur);
        SA[cur].len = SA[last].len + 1;
        FirstPos[cur] = SA[cur].len - 1;
        NumOcc[cur] = 1;
        lenState.push_back(make_pair(SA[cur].len, cur));
        for (p = last; p != -1 && SA[p].nxtc.count(ch) == 0; p = SA[p].link) SA[p].nxtc[ch] = cur;
        if (p == -1) SA[cur].link = 0;
        else
        {
            q = SA[p].nxtc[ch];
            if (SA[p].len + 1 == SA[q].len) SA[cur].link = q;
            else
            {
                clone = sz++;
                init(clone);
                SA[clone] = SA[q];
                SA[clone].len = SA[p].len + 1;
                for (; p != -1 && SA[p].nxtc[ch] == q; p = SA[p].link) SA[p].nxtc[ch] = clone;
                SA[cur].link = SA[q].link = clone;
                FirstPos[clone] = FirstPos[q];
                NumOcc[clone] = 0;
                lenState.push_back(make_pair(SA[clone].len, clone));
            }
        }
        last = cur;
    }
    void traverse(char *str)
    {
        if (traverse(0, str) == 0) puts("not a substring");
    }
    int distSubs()
    {
        int i;
        memset(vis, false, sizeof(vis));
        sort(lenState.begin(), lenState.end());
        for (i=lenState.size()-1; i>=0; --i) distSubs(lenState[i].second);
        return distSubs(0);
    }
    void numOcc()
    {
        int i,p,q;
        sort(lenState.begin(), lenState.end());
        for (i=lenState.size()-1; i>=0; --i)
        {
            //printf("%d %d\n", lenState[i].first, lenState[i].second);
            q = lenState[i].second;
            p = SA[q].link;
            if (p<1) continue;
            NumOcc[p] += NumOcc[q];
        }
    }
    __int64 count()
    {
        int i,p,q,d;
        __int64 ret;
        ret = 0;
        for (q=1; q<sz; ++q)
        {
            p = SA[q].link;
            d = SA[q].len - SA[p].len;
            ret += (__int64) d * f(NumOcc[q]);
        }
        return ret;
    }
};
int main()
{
    int i;
    while(scanf("%s", str) != EOF)
    {
        SuffixAutomata sa;
        for (i=0; str[i]; ++i) sa.extend(str[i]);
        sa.numOcc();
        printf("%I64d\n", sa.count());
    }
    return 0;
}


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
#include<set>
#include<map>
#include<utility>
#include<vector>
#include<string>
#include<stack>
#include<queue>
using namespace std;
#define MAXLEN 100006
struct State
{
    int len, link;
    map < char , int > nxtc;
} SA[2*MAXLEN];
int FirstPos[2*MAXLEN], DistSub[2*MAXLEN], NumOcc[2*MAXLEN];
bool vis[2*MAXLEN];
char str[MAXLEN];
vector < pair < int , int > > lenState;
__int64 f(int n)
{
    __int64 ret = n;
    ret *= (n+1);
    return ret/2;
}
class SuffixAutomata
{
    int sz, last;
    void init(int idx)
    {
        SA[idx].len = 0, SA[idx].link = -1;
        FirstPos[idx] = -1;
        SA[idx].nxtc.clear();
    }
    bool traverse(int cur, char *ch)
    {
        if (*ch == 0)
        {
            printf("first occurance lasts at = %d :: total # of occurances = %d :: node = %d\nlink = %d :: len = %d\n", FirstPos[cur], NumOcc[cur], cur, SA[cur].link, SA[cur].len);
            return true;
        }
        if (SA[cur].nxtc.count(*ch) == 0) return false;
        int p = SA[cur].nxtc[*ch];
        return traverse(p, ++ch);
    }
    int distSubs(int cur)
    {
        if (vis[cur]) return DistSub[cur];
        vis[cur] = true;
        if (cur) DistSub[cur] = 1;
        else DistSub[cur] = 0;
        map < char , int > :: iterator im;
        map < char , int > &M = SA[cur].nxtc;
        for (im = M.begin(); im != M.end(); ++im) DistSub[cur] += distSubs(im->second);
        return DistSub[cur];
    }
public:
    SuffixAutomata()
    {
        sz = last = 0;
        init(0);
        lenState.clear();
        ++sz;
    }
    int size() {return sz;}
    void extend(char ch)
    {
        int p, q, clone, cur = sz++;
        init(cur);
        SA[cur].len = SA[last].len + 1;
        FirstPos[cur] = SA[cur].len - 1;
        NumOcc[cur] = 1;
        lenState.push_back(make_pair(SA[cur].len, cur));
        for (p = last; p != -1 && SA[p].nxtc.count(ch) == 0; p = SA[p].link) SA[p].nxtc[ch] = cur;
        if (p == -1) SA[cur].link = 0;
        else
        {
            q = SA[p].nxtc[ch];
            if (SA[p].len + 1 == SA[q].len) SA[cur].link = q;
            else
            {
                clone = sz++;
                init(clone);
                SA[clone] = SA[q];
                SA[clone].len = SA[p].len + 1;
                for (; p != -1 && SA[p].nxtc[ch] == q; p = SA[p].link) SA[p].nxtc[ch] = clone;
                SA[cur].link = SA[q].link = clone;
                FirstPos[clone] = FirstPos[q];
                NumOcc[clone] = 0;
                lenState.push_back(make_pair(SA[clone].len, clone));
            }
        }
        last = cur;
    }
    void traverse(char *str)
    {
        if (traverse(0, str) == 0) puts("not a substring");
    }
    int distSubs()
    {
        int i;
        memset(vis, false, sizeof(vis));
        sort(lenState.begin(), lenState.end());
        for (i=lenState.size()-1; i>=0; --i) distSubs(lenState[i].second);
        return distSubs(0);
    }
    void numOcc()
    {
        int i,p,q;
        sort(lenState.begin(), lenState.end());
        for (i=lenState.size()-1; i>=0; --i)
        {
            //printf("%d %d\n", lenState[i].first, lenState[i].second);
            q = lenState[i].second;
            p = SA[q].link;
            if (p<1) continue;
            NumOcc[p] += NumOcc[q];
        }
    }
    __int64 count()
    {
        int i,p,q,d;
        __int64 ret;
        ret = 0;
        for (q=1; q<sz; ++q)
        {
            p = SA[q].link;
            d = SA[q].len - SA[p].len;
            ret += (__int64) d * f(NumOcc[q]);
        }
        return ret;
    }
};
int main()
{
    int i;
    while(scanf("%s", str) != EOF)
    {
        SuffixAutomata sa;
        for (i=0; str[i]; ++i) sa.extend(str[i]);
        sa.numOcc();
        printf("%I64d\n", sa.count());
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
namespace SuffixAutomaton {
	const int MAXN = 100005;
	const int MAXC = 26;
	int root, size, last;
	int child[MAXN][MAXC];
	int fail[MAXN], depth[MAXN], cnt[MAXN];
	vector <int> a[MAXN];
	long long ans;
	int newnode(int dep) {
		fail[size] = 0;
		depth[size] = dep;
		memset(child[size], 0, sizeof(child[size]));
		return size++;
	}
	void extend(int ch) {
		int p = last, np = newnode(depth[last] + 1);
		while (child[p][ch] == 0) {
			child[p][ch] = np;
			p = fail[p];
		}
		if (child[p][ch] == np) fail[np] = root;
		else {
			int q = child[p][ch];
			if (depth[q] == depth[p] + 1) fail[np] = q;
			else {
				int nq = newnode(depth[p] + 1);
				fail[nq] = fail[q];
				fail[q] = fail[np] = nq;
				memcpy(child[nq], child[q], sizeof(child[q]));
				while (child[p][ch] == q) {
					child[p][ch] = nq;
					p = fail[p];
				}
			}
		}
		cnt[last = np]++;
	}
	void init(char *s) {
		size = 0;
		root = last = newnode(0);
		int len = strlen(s + 1);
		for (int i = 1; i <= len; i++)
			extend(s[i] - 'a');
	}
	long long f(long long x) {return x * (x + 1) / 2; }
	void work(int pos) {
		for (unsigned i = 0; i < a[pos].size(); i++) {
			work(a[pos][i]);
			cnt[pos] += cnt[a[pos][i]];
		}
		ans += f(cnt[pos]) * (depth[pos] - depth[fail[pos]]);
	}
	void calc() {
		for (int i = 1; i < size; i++)
			a[fail[i]].push_back(i);
		work(0);
		writeln(ans);
	}
}
char s[MAXN];
int main() {
	scanf("%s", s + 1);
	SuffixAutomaton::init(s);
	SuffixAutomaton::calc();
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
namespace SuffixAutomaton {
	const int MAXN = 100005;
	const int MAXC = 26;
	int root, size, last;
	int child[MAXN][MAXC];
	int fail[MAXN], depth[MAXN], cnt[MAXN];
	vector <int> a[MAXN];
	long long ans;
	int newnode(int dep) {
		fail[size] = 0;
		depth[size] = dep;
		memset(child[size], 0, sizeof(child[size]));
		return size++;
	}
	void extend(int ch) {
		int p = last, np = newnode(depth[last] + 1);
		while (child[p][ch] == 0) {
			child[p][ch] = np;
			p = fail[p];
		}
		if (child[p][ch] == np) fail[np] = root;
		else {
			int q = child[p][ch];
			if (depth[q] == depth[p] + 1) fail[np] = q;
			else {
				int nq = newnode(depth[p] + 1);
				fail[nq] = fail[q];
				fail[q] = fail[p] = nq;
				memcpy(child[nq], child[q], sizeof(child[q]));
				while (child[p][ch] == q) {
					child[p][ch] = nq;
					p = fail[p];
				}
			}
		}
		cnt[last = np]++;
	}
	void init(char *s) {
		size = 0;
		root = last = newnode(0);
		int len = strlen(s + 1);
		for (int i = 1; i <= len; i++)
			extend(s[i] - 'a');
	}
	long long f(long long x) {return x * (x + 1) / 2; }
	void work(int pos) {
		for (unsigned i = 0; i < a[pos].size(); i++) {
			work(a[pos][i]);
			cnt[pos] += cnt[a[pos][i]];
		}
		ans += f(cnt[pos]) * (depth[pos] - depth[fail[pos]]);
	}
	void calc() {
		for (int i = 1; i < size; i++)
			a[fail[i]].push_back(i);
		work(0);
		writeln(ans);
	}
}
char s[MAXN];
int main() {
	scanf("%s", s + 1);
	SuffixAutomaton::init(s);
	SuffixAutomaton::calc();
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {
	x = 0; int f = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
	for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
	x *= f;
}
template <typename T> void write(T x) {
	if (x < 0) x = -x, putchar('-');
	if (x > 9) write(x / 10);
	putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
	write(x);
	puts("");
}
namespace SuffixAutomaton {
	const int MAXN = 2 * 100005;
	const int MAXC = 26;
	int root, size, last;
	int child[MAXN][MAXC];
	int fail[MAXN], depth[MAXN], cnt[MAXN];
	vector <int> a[MAXN];
	long long ans;
	int newnode(int dep) {
		fail[size] = 0;
		depth[size] = dep;
		memset(child[size], 0, sizeof(child[size]));
		return size++;
	}
	void extend(int ch) {
		int p = last, np = newnode(depth[last] + 1);
		while (child[p][ch] == 0) {
			child[p][ch] = np;
			p = fail[p];
		}
		if (child[p][ch] == np) fail[np] = root;
		else {
			int q = child[p][ch];
			if (depth[q] == depth[p] + 1) fail[np] = q;
			else {
				int nq = newnode(depth[p] + 1);
				fail[nq] = fail[q];
				fail[q] = fail[np] = nq;
				memcpy(child[nq], child[q], sizeof(child[q]));
				while (child[p][ch] == q) {
					child[p][ch] = nq;
					p = fail[p];
				}
			}
		}
		cnt[last = np]++;
	}
	void init(char *s) {
		size = 0;
		root = last = newnode(0);
		int len = strlen(s + 1);
		for (int i = 1; i <= len; i++)
			extend(s[i] - 'a');
	}
	long long f(long long x) {return x * (x + 1) / 2; }
	void work(int pos) {
		for (unsigned i = 0; i < a[pos].size(); i++) {
			work(a[pos][i]);
			cnt[pos] += cnt[a[pos][i]];
		}
		ans += f(cnt[pos]) * (depth[pos] - depth[fail[pos]]);
	}
	void calc() {
		for (int i = 1; i < size; i++)
			a[fail[i]].push_back(i);
		work(0);
		writeln(ans);
	}
}
char s[MAXN];
int main() {
	scanf("%s", s + 1);
	SuffixAutomaton::init(s);
	SuffixAutomaton::calc();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 110000;

struct ss {
	int x, y, p;
};

int n, p[19][N], pas, cnt, sf[N], x[N];
long long rez;
char a[N];
ss s[N];

bool cmp(ss a, ss b) {
	if(a.x == b.x)
		return a.y < b.y;
	return a.x < b.x;
}

void suffArray() {
	int i;

	for(i = 0; i < n; ++i)
		p[0][i] = a[i] - 'a';

	for(pas = 1, cnt = 2; cnt <= n; cnt *= 2, ++pas) {

		for(i = 0; i < n; ++i) {
			s[i].x = p[pas - 1][i];
			s[i].y = (i + cnt/2 < n ? p[pas - 1][i + cnt/2] : -1);
			s[i].p = i;
		}

		sort(s, s + n, cmp);
		for(i = 0; i < n; ++i) {
			if(i != 0 && s[i].x == s[i - 1].x && s[i].y == s[i - 1].y)
				p[pas][s[i].p] = p[pas][s[i - 1].p];
			else
				p[pas][s[i].p] = i;
		}
	}
	--pas;

	for(i = 0; i < n; ++i)
		sf[i] = s[i].p;
}

inline int lcp(int a, int b) {
	int k, r = 0;
	for(k = pas; k>= 0 && a < n && b < n; --k)
		if(p[k][a] == p[k][b]) {
			a += (1<<k);
			b += (1<<k);
			r += (1<<k);
		}
	return r;
}

bool ver[N];
int cs[N], cd[N], st[N], nr;
vector<int> ext[N];

void calc() {
	int i, j;

	for(i = 0; i < n - 1; ++i)
		x[i] = lcp(sf[i], sf[i + 1]);

	rez += n - sf[0] - x[0] + n - sf[n - 1] - x[n - 2];
	for(i = 1; i < n - 1; ++i)
		rez += n - sf[i] - max(x[i - 1], x[i]);

	x[n - 1] = -1;
	for(i = 0; i < n; ++i) {
		while(nr && x[st[nr]] > x[i]) {
			cd[st[nr]] = i - 1;
			--nr;
		}
		st[++nr] = i;
		cs[i] = st[nr - 1] + (nr == 1 ? 0 : 1);
	}
	x[n - 1] = 0;
	for(i = 0; i < n - 1; ++i) {

		for(j = 0; j < ext[i].size(); ++j)
			ver[ext[i][j]] = 0;

		int nrel = cd[i] - cs[i] + 2;
		if(ver[nrel])
			continue;

		rez += 1LL * nrel * (nrel + 1)/2 * (x[i] - max(x[cd[i] + 1], cs[i] == 0 ? 0 : x[cs[i] - 1]));
		ver[nrel] = 1;
		ext[cd[i] + 1].push_back(nrel);
	}
}

int main() {
	//freopen("ttt", "r", stdin);

	cin >> a;

	n = strlen(a);

	suffArray();

	calc();

	cout << rez;

	return 0;
}


#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

const int N = 110000;

struct ss {
	int x, y, p;
};

int n, p[19][N], pas, cnt, sf[N], x[N];
long long rez;
char a[N];
ss s[N];

bool cmp(ss a, ss b) {
	if(a.x == b.x)
		return a.y < b.y;
	return a.x < b.x;
}

void suffArray() {
	int i;

	for(i = 0; i < n; ++i)
		p[0][i] = a[i] - 'a';

	for(pas = 1, cnt = 2;; cnt *= 2, ++pas) {

		for(i = 0; i < n; ++i) {
			s[i].x = p[pas - 1][i];
			s[i].y = (i + cnt/2 < n ? p[pas - 1][i + cnt/2] : -1);
			s[i].p = i;
		}

		sort(s, s + n, cmp);
		for(i = 0; i < n; ++i) {
			if(i != 0 && s[i].x == s[i - 1].x && s[i].y == s[i - 1].y)
				p[pas][s[i].p] = p[pas][s[i - 1].p];
			else
				p[pas][s[i].p] = i;
		}

		if(cnt >= n) {
			break;
		}
	}

	for(i = 0; i < n; ++i)
		sf[i] = s[i].p;
}

inline int lcp(int a, int b) {
	int k, r = 0;
	for(k = pas; k>= 0 && a < n && b < n; --k)
		if(p[k][a] == p[k][b]) {
			a += (1<<k);
			b += (1<<k);
			r += (1<<k);
		}
	return r;
}

bool ver[N];
int cs[N], cd[N], st[N], nr;
vector<int> ext[N];

void calc() {
	int i, j;

	for(i = 0; i < n - 1; ++i)
		x[i] = lcp(sf[i], sf[i + 1]);

	rez += n - sf[0] - x[0] + n - sf[n - 1] - x[n - 2];
	for(i = 1; i < n - 1; ++i)
		rez += n - sf[i] - max(x[i - 1], x[i]);

	x[n - 1] = -1;
	for(i = 0; i < n; ++i) {
		while(nr && x[st[nr]] > x[i]) {
			cd[st[nr]] = i - 1;
			--nr;
		}
		st[++nr] = i;
		cs[i] = st[nr - 1] + (nr == 1 ? 0 : 1);
	}
	x[n - 1] = 0;
	for(i = 0; i < n - 1; ++i) {

		for(j = 0; j < ext[i].size(); ++j)
			ver[ext[i][j]] = 0;

		int nrel = cd[i] - cs[i] + 2;
		if(ver[nrel])
			continue;

		rez += 1LL * nrel * (nrel + 1)/2 * (x[i] - max(x[cd[i] + 1], cs[i] == 0 ? 0 : x[cs[i] - 1]));
		ver[nrel] = 1;
		ext[cd[i] + 1].push_back(nrel);
	}
}

int main() {
	//freopen("ttt", "r", stdin);

	cin >> a;

	n = strlen(a);

	suffArray();

	calc();

	cout << rez;

	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define mem(a) memset(a,0,sizeof(a))
#define down(i,j,k) for (i=j;i>=k;i--)
#define rep(i,j,k) for (i=j;i<=k;i++)
const int N=1e5+5;
using namespace std;
struct suffix{
	int n,i,k,dbg,hd[N],sa[N],rk[N*2],RK[N],cnt[N],h[N];
	int tp,wh[N],lim[N];
	char s[N];
	bool cmp(int x,int y)
	{
		if (rk[x]==rk[y] && rk[x+k]==rk[y+k]) return 1;
		return 0;
	}
	void read()
	{
		scanf("%s",s+1);
		n=strlen(s+1);
		dbg=0;
	}
	void debug()
	{
		int i;
		dbg++;
		printf("debug#%d:\n",dbg);
		printf("S :"); rep(i,1,n) printf("%c ",s[i]); putchar('\n');
		printf("SA:"); rep(i,1,n) printf("%d ",sa[i]); putchar('\n');
		printf("rk:"); rep(i,1,n) printf("%d ",rk[i]); putchar('\n');
		printf("h :"); rep(i,1,n) printf("%d ",h[i]); putchar('\n');
		printf("\n");
	}
	void init()
	{
		int i,hn;
		mem(cnt);
		rep(i,1,n) cnt[s[i]-'a'+1]++;
		rep(i,1,26) cnt[i]+=cnt[i-1];
		rep(i,1,n) rk[i]=cnt[s[i]-'a'+1];
		rep(i,1,n) sa[cnt[s[i]-'a'+1]--]=i;
		for (k=1;k<n;k<<=1)
		{
			hn=0;
			rep(i,n-k+1,n) hd[++hn]=i;
			rep(i,1,n)
				if (sa[i]>k) hd[++hn]=sa[i]-k;
			mem(cnt);
			rep(i,1,n) cnt[rk[i]]++;
			rep(i,1,n) cnt[i]+=cnt[i-1];
			down(i,n,1) sa[cnt[rk[hd[i]]]--]=hd[i];
			RK[sa[1]]=hn=1;
			rep(i,2,n)
				if (cmp(sa[i-1],sa[i])) RK[sa[i]]=hn;
				else RK[sa[i]]=++hn;
			memcpy(rk,RK,sizeof(RK[1])*(n+1));
		}
	}
	void calc_hi()
	{
		int i,l=0;
		rep(i,1,n)
		{
			if (l>0) l--;
			while (i+l<=n && sa[rk[i]-1]+l<=n && s[i+l]==s[sa[rk[i]-1]+l]) l++;
			h[rk[i]]=l;
		}
	}
	LL work()
	{
		LL ans=0;
		int p,i,bsc,flg=0;
		wh[tp=1]=n+1; lim[1]=0;
		down(i,n,1)
		{
			p=n-sa[i]+1; flg=0;
			while (lim[tp]>h[i]) {
				bsc=max(lim[tp-1],h[i]);
				if (p>bsc) {
					ans+=(LL)(p-bsc)*(wh[tp]-i+1)*(wh[tp]-i+2)/2;
					p=bsc;
				}
				tp--; flg=1;
			}
			if (h[i]<p) ans+=p-h[i];
			if (h[i]>lim[tp]) {tp++; lim[tp]=h[i]; if (!flg) wh[tp]=i;}
		}
		return ans;
	}
}suf;
int main()
{
//	freopen("string.in","r",stdin);
//	freopen("string.out","w",stdout);
	suf.read();
	suf.init();
	suf.calc_hi();
//	suf.debug();
	printf("%I64d\n",suf.work());
	return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define mem(a) memset(a,0,sizeof(a))
#define down(i,j,k) for (i=j;i>=k;i--)
#define rep(i,j,k) for (i=j;i<=k;i++)
const int N=1e5+5;
using namespace std;
struct suffix{
	int n,i,k,dbg,hd[N],sa[N],rk[N*2],RK[N],cnt[N],h[N];
	int tp,wh[N],lim[N];
	char s[N];
	bool cmp(int x,int y)
	{
		if (rk[x]==rk[y] && rk[x+k]==rk[y+k]) return 1;
		return 0;
	}
	void read()
	{
		scanf("%s",s+1);
		n=strlen(s+1);
		dbg=0;
	}
	void debug()
	{
		int i;
		dbg++;
		printf("debug#%d:\n",dbg);
		printf("S :"); rep(i,1,n) printf("%c ",s[i]); putchar('\n');
		printf("SA:"); rep(i,1,n) printf("%d ",sa[i]); putchar('\n');
		printf("rk:"); rep(i,1,n) printf("%d ",rk[i]); putchar('\n');
		printf("h :"); rep(i,1,n) printf("%d ",h[i]); putchar('\n');
		printf("\n");
	}
	void init()
	{
		int i,hn;
		mem(cnt);
		rep(i,1,n) cnt[s[i]-'a'+1]++;
		rep(i,1,26) cnt[i]+=cnt[i-1];
		rep(i,1,n) rk[i]=cnt[s[i]-'a'+1];
		rep(i,1,n) sa[cnt[s[i]-'a'+1]--]=i;
		for (k=1;k<n;k<<=1)
		{
			hn=0;
			rep(i,n-k+1,n) hd[++hn]=i;
			rep(i,1,n)
				if (sa[i]>k) hd[++hn]=sa[i]-k;
			mem(cnt);
			rep(i,1,n) cnt[rk[i]]++;
			rep(i,1,n) cnt[i]+=cnt[i-1];
			down(i,n,1) sa[cnt[rk[hd[i]]]--]=hd[i];
			RK[sa[1]]=hn=1;
			rep(i,2,n)
				if (cmp(sa[i-1],sa[i])) RK[sa[i]]=hn;
				else RK[sa[i]]=++hn;
			memcpy(rk,RK,sizeof(RK[1])*(n+1));
		}
	}
	void calc_hi()
	{
		int i,l=0;
		rep(i,1,n)
		{
			if (l>0) l--;
			while (i+l<=n && sa[rk[i]-1]+l<=n && s[i+l]==s[sa[rk[i]-1]+l]) l++;
			h[rk[i]]=l;
		}
	}
	LL work()
	{
		LL ans=0;
		int p,i,bsc,flg=0;
		wh[tp=1]=n+1; lim[1]=0;
		down(i,n,1)
		{
			p=n-sa[i]+1; flg=0;
			if (lim[tp]>h[i])
				if (p>lim[tp]) ans+=p-lim[tp],p=lim[tp];
			while (lim[tp]>h[i]) {
				bsc=max(lim[tp-1],h[i]);
				if (p>bsc) {
					ans+=(LL)(p-bsc)*(wh[tp]-i+1)*(wh[tp]-i+2)/2;
					p=bsc;
				}
				tp--; flg=1;
			}
			if (h[i]<p) ans+=p-h[i];
			if (h[i]>lim[tp]) {tp++; lim[tp]=h[i]; if (!flg) wh[tp]=i;}
		}
		return ans;
	}
}suf;
int main()
{
	//freopen("string.in","r",stdin);
	//freopen("string.out","w",stdout);
	suf.read();
	suf.init();
	suf.calc_hi();
//	suf.debug();
	printf("%I64d\n",suf.work());
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <cassert>

using namespace std;

char buf[300000];
int aut[600000][26];
int suf[600000];
int d[600000], r[600000];
long long wsv[600000];
long long resv[600000];
bool f[600000];

long long calc(int v, long long *ws) {
  if (wsv[v]) {
    *ws = wsv[v];
    return resv[v];
  }
  long long cws = 0, tws, res = 0;
  for (int i = 0; i < 26; i++) {
    if (aut[v][i]) {
      res += calc (aut[v][i], &tws);
      cws += tws;
    }
  }
  if (f[v]) ++cws;
  res += cws * (cws + 1) / 2;
  *ws = cws;
  wsv[v] = cws;
  resv[v] = res;
  assert (cws > 0);
  //cerr << v << " " << res << '\n';
  return res;
}

int main() {
  gets(buf);
  int l = strlen(buf);
  int ls = 1, lx = 2;
  for (int i = 0; i < 26; i++) aut[0][i] = 1;
  r[1] = 1;
  for (int i = 0; i < l; i++) {
    int cc = buf[i] - 'a';
    int cur = ls;
    do {
      aut[cur][cc] = lx;
      r[lx] += r[cur];
      cur = suf[cur];
    } while (cur && !aut[cur][cc]);
    d[lx] = d[ls] + 1;
    int lc = 1;
    int nx = aut[cur][cc];
    if (cur) {
      if (d[cur] + 1 != d[nx]) {
	int nw = lx + 1;
	memcpy(aut[nw], aut[nx], 26 * 4);
	suf[nw] = suf[nx];
	suf[nx] = nw;
	do {
	  r[nx] -= r[cur];
	  r[nw] += r[cur];
	  aut[cur][cc] = nw;
	  cur = suf[cur];
	} while (aut[cur][cc] == nx);
	nx = nw;
	lc = 2;
      }
    }
    suf[lx] = nx;
    ls = lx;
    lx += lc;
  }
  /*for (int i = 1; i < lx; i++) {
    printf("suf[%d] = %d, r[%d] = %d, d[%d] = %d\n", i, suf[i], i, r[i], i, d[i]);
    for (int j = 0; j < 26; j++) {
      if (aut[i][j]) {
	printf ("(%d, %c) -> %d\n", i, j + 97, aut[i][j]);
      }
    }
    }*/
  int sum = 0;
  for (int cur = ls; cur; cur = suf[cur]) f[cur] = true, sum += r[cur];
  assert (sum == l + 1);
  long long tmp;
  long long res = calc (1, &tmp) - (long long)(l + 1) * (l + 2) / 2;
  assert (tmp == l + 1);
  cout << res << '\n';
  return 0;
}


#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>

char s[300000];
using namespace std;
int L;

//KOTEHOK's code from MM18
#define INF 1000000000
#define Alph 27

struct node;

//Suffix tree edge
struct edge {
  int beg, len, exmp;
  node *to;
};

//Suffix tree node
struct node {
  node *suffix;
  edge *uplink;
  edge *links [Alph];
};

edge edges[300000];
node nodes[300000];
int next_edge, next_node;

inline edge *new_edge () {
  edge *ret = &edges[next_edge++];
  //printf ("%d\n", next_edge);
  return ret;
};

inline node *new_node () {
  node *ret = &nodes[next_node++];
  //printf ("%d\n", next_node);
  ret -> suffix = NULL;
  /*for (int x = 0; x < Alph; x++)
    ret -> links [x] = NULL;*/
  memset (ret -> links, 0, sizeof (ret -> links));
  return ret;
};

struct SuffixTree {
  int pos, bpos;          //position in buf, last added position in buf
  node *root;             //root of the tree
  edge *root_edge;        //root edge (hang)
  edge *last_edge;        //last edge of operation
  node *last_node;        //last node of operation
  node *last_split;       //last split
  int last_pos;           //last position
  char *buf;              //string buffer

  inline void init_tree () {
    root = new_node ();
    root_edge = new_edge ();
    root_edge -> to = root;
    root_edge -> beg = 0;
    root_edge -> len = 0;
    root_edge -> exmp = -1;
    root -> uplink = root_edge;
    pos = 0;
    bpos = 0;
    last_node = NULL;
    last_split = NULL;
    last_pos = 0;
    last_edge = root_edge;
  };

  inline void append_char (int x) {
    //printf ("adding: %c\n", x + 96);
    assert ((x >= 0) && (x < Alph));
    do {
      //printf ("  bpos = %d: last_pos = %d, next_edge = %d, last_edge = %p\n", bpos, last_pos, next_edge, last_edge);
      node *temp;
      edge *etemp;
      int skipcount;
      if (last_pos == last_edge -> len) {
        //printf ("  bpos = %d: case vertex\n", bpos);
        temp = last_edge -> to;
        if (last_split != NULL) last_split -> suffix = temp;
        last_split = NULL;
        if (temp -> links [x] != NULL) {
          last_edge = temp -> links [x];
          last_node = temp;
          last_pos = 1;
          break;
        };
        etemp = new_edge ();
        temp -> links [x] = etemp;
        skipcount = 0;
      } else {
        //printf ("  bpos = %d: case edge\n", bpos);
        int wchar = buf [last_edge -> beg + last_pos];
        if (x == wchar) {
          ++last_pos;
          break;
        };
        temp = new_node ();
        temp -> uplink = last_edge;
        etemp = new_edge ();
        temp -> links [wchar] = etemp;
        etemp -> beg = last_edge -> beg + last_pos;
        etemp -> len = (last_edge -> len == INF) ? INF : last_edge -> len - last_pos;
        etemp -> exmp = last_edge -> exmp;
        etemp -> to = last_edge -> to;
        if (etemp -> to != NULL) etemp -> to -> uplink = etemp;
        last_edge -> len = last_pos;
        last_edge -> to = temp;
        if (last_split != NULL) last_split -> suffix = temp;
        last_split = temp;
        etemp = new_edge ();
        temp -> links [x] = etemp;
        temp = last_node;
        skipcount = last_pos;
      };
      etemp -> beg = pos;
      etemp -> len = INF;
      etemp -> exmp = bpos;
      etemp -> to = NULL;
      //printf ("  returned to case general\n");

      temp = temp -> suffix;
      if (temp == NULL) {
        last_node = NULL;
        last_pos = 0;
        last_edge = root_edge;
        if (skipcount == 0) {
          ++bpos;
          break;
        } else {
          --skipcount;
          temp = root;
        };
      } else
	if (skipcount == 0) {
	  last_edge = temp -> uplink;
	  last_pos = last_edge -> len;
	};

      //do skip/count
      while (skipcount) {
        char wchar = buf [pos - skipcount];
        etemp = temp -> links[(int)wchar];
        assert (etemp != NULL);
        if (skipcount <= etemp -> len) {
          last_edge = etemp;
          last_node = temp;
          last_pos = skipcount;
          break;
        };
        skipcount -= etemp -> len;
        temp = etemp -> to;
      };
      ++bpos;
    } while (1);
    assert (last_split == NULL);
    assert (root -> links [x] != NULL);
    //printf ("returned\n");
  };

  inline void build_tree (char *str) {
    init_tree ();
    buf = str;
    for (;*str;++str) {
      *str -= 'a' - 1;
      append_char (*str);
      ++pos;
    };
    append_char (0);
  };

  long long calc (node *n, int skip, long long *sz) {
    long long res = 0, csz = 0, tsz, clen;
    for (int i = 0; i < Alph; i++) {
      if (n->links[i]) {
	if (n->links[i]->len == INF) {
	  ++csz;
	  clen = L - n->links[i]->beg;
	  res += clen;
	} else {
	  res += calc (n->links[i]->to, n->links[i]->len, &tsz);
	  csz += tsz;
	}
      }
    }
    res += skip * csz * (csz + 1) / 2;
    *sz = csz;
    return res;
  }
};

SuffixTree t;

int main () {
  gets (s);
  L = strlen (s);
  t.build_tree (s);
  long long tmp = -1;
  cout << t.calc (t.root, 0, &tmp) << '\n';
  //cerr << tmp << '\n';
  assert (tmp == L + 1);
  return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <cassert>

using namespace std;

char buf[300000];
int aut[600000][26];
int suf[600000];
int d[600000], r[600000];
long long wsv[600000];
long long resv[600000];
bool f[600000];

long long calc(int v, long long *ws) {
  if (wsv[v]) {
    *ws = wsv[v];
    return resv[v];
  }
  long long cws = 0, tws, res = 0;
  for (int i = 0; i < 26; i++) {
    if (aut[v][i]) {
      res += calc (aut[v][i], &tws);
      cws += tws;
    }
  }
  if (f[v]) ++cws;
  res += cws * (cws + 1) / 2;
  *ws = cws;
  wsv[v] = cws;
  resv[v] = res;
  assert (cws > 0);
  //cerr << v << " " << res << '\n';
  return res;
}

int main() {
  gets(buf);
  int l = strlen(buf);
  int ls = 1, lx = 2;
  for (int i = 0; i < 26; i++) aut[0][i] = 1;
  r[1] = 1;
  for (int i = 0; i < l; i++) {
    int cc = buf[i] - 'a';
    int cur = ls;
    do {
      aut[cur][cc] = lx;
      r[lx] += r[cur];
      cur = suf[cur];
    } while (!aut[cur][cc]);
    d[lx] = d[ls] + 1;
    int lc = 1;
    int nx = aut[cur][cc];
    if (cur && d[cur] + 1 != d[nx]) {
      int nw = lx + 1;
      memcpy(aut[nw], aut[nx], 26 * 4);
      suf[nw] = suf[nx];
      suf[nx] = nw;
      do {
	r[nx] -= r[cur];
	r[nw] += r[cur];
	aut[cur][cc] = nw;
	cur = suf[cur];
      } while (aut[cur][cc] == nx);
      nx = nw;
      lc = 2;
    }
    suf[lx] = nx;
    ls = lx;
    lx += lc;
  }
  /*for (int i = 1; i < lx; i++) {
    printf("suf[%d] = %d, r[%d] = %d, d[%d] = %d\n", i, suf[i], i, r[i], i, d[i]);
    for (int j = 0; j < 26; j++) {
      if (aut[i][j]) {
	printf ("(%d, %c) -> %d\n", i, j + 97, aut[i][j]);
      }
    }
    }*/
  int sum = 0;
  for (int cur = ls; cur; cur = suf[cur]) f[cur] = true, sum += r[cur];
  assert (sum == l + 1);
  long long tmp;
  long long res = calc (1, &tmp) - (long long)(l + 1) * (l + 2) / 2;
  assert (tmp == l + 1);
  cout << res << '\n';
  return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <cassert>

using namespace std;

char buf[300000];
int aut[600000][26];
int suf[600000];
int d[600000], r[600000];
bool f[600000];

long long calc(int v, long long *ws) {
  long long cws = 0, tws, res = 0;
  for (int i = 0; i < 26; i++) {
    if (aut[v][i]) {
      res += calc (aut[v][i], &tws);
      cws += tws;
    }
  }
  if (f[v]) ++cws;
  res += cws * (cws + 1) / 2;
  *ws = cws;
  //cerr << v << " " << res << '\n';
  return res;
}

int main() {
  gets(buf);
  int l = strlen(buf);
  int ls = 1, lx = 2;
  for (int i = 0; i < 26; i++) aut[0][i] = 1;
  r[1] = 1;
  for (int i = 0; i < l; i++) {
    int cc = buf[i] - 'a';
    int cur = ls;
    do {
      aut[cur][cc] = lx;
      r[lx] += r[cur];
      cur = suf[cur];
    } while (cur && !aut[cur][cc]);
    d[lx] = d[ls] + 1;
    int lc = 1;
    int nx = aut[cur][cc];
    if (cur) {
      if (d[cur] + 1 != d[nx]) {
	int nw = lx + 1;
	memcpy(aut[nw], aut[nx], 26 * 4);
	suf[nw] = suf[nx];
	suf[nx] = nw;
	do {
	  r[nx] -= r[cur];
	  r[nw] += r[cur];
	  aut[cur][cc] = nw;
	  cur = suf[cur];
	} while (aut[cur][cc] == nx);
	nx = nw;
	lc = 2;
      }
    }
    suf[lx] = nx;
    ls = lx;
    lx += lc;
  }
  /*for (int i = 1; i < lx; i++) {
    printf("suf[%d] = %d, r[%d] = %d, d[%d] = %d\n", i, suf[i], i, r[i], i, d[i]);
    for (int j = 0; j < 26; j++) {
      if (aut[i][j]) {
	printf ("(%d, %c) -> %d\n", i, j + 97, aut[i][j]);
      }
    }
    }*/
  int sum = 0;
  for (int cur = ls; cur; cur = suf[cur]) f[cur] = true, sum += r[cur];
  assert (sum == l + 1);
  long long tmp;
  long long res = calc (1, &tmp) - (long long)(l + 1) * (l + 2) / 2;
  assert (tmp == l + 1);
  cout << res << '\n';
  return 0;
}


#include <cstdio>
#include <cstring>
inline unsigned int getuint(){
	char w=getchar();
	while (w<'0'||'9'<w) w=getchar();
	unsigned int ans=0;
	for (;'0'<=w&&w<='9';w=getchar()) ans=ans*10+w-'0';
	return ans;
}
int n;
char str[100005];
struct Suffix_AutoMaton{
	struct node{
		node *s[26], *p;
		int maxlen, cnt;
	} pool[100005<<1], *poolnow, *root;
	node *insert(node *p, int f){
		node *np=poolnow++;np->maxlen=p->maxlen+1;
		for (;p&&!p->s[f];p=p->p) p->s[f]=np;
		if (p)
			if (p->s[f]->maxlen!=p->maxlen+1){
				node *q=p->s[f], *nq=poolnow++;
				memcpy(nq->s, q->s, sizeof(q->s)), nq->p=q->p, q->maxlen=p->maxlen+1, q->p=np->p=nq;
				for (;p&&p->s[f]==q;p=p->p) p->s[f]=nq;
			} else np->p=p->s[f];
		else np->p=root;
		return np;
	}
	int c[100005];
	node *a[100005<<1];
	void solve(){
		root=(poolnow=pool)++;
		node *last=root;
		for (int i=1;i<=n;i++) (last=insert(last, str[i]-'a'))->cnt=1;
		for (node *p=pool;p!=poolnow;p++) c[p->maxlen]++;
		for (int i=1;i<=n;i++) c[i]+=c[i-1];
		for (node *p=pool;p!=poolnow;p++) a[c[p->maxlen]--]=p;
		for (int i=poolnow-pool;i>1;i--) a[i]->p->cnt+=a[i]->cnt;
		root->cnt=0;
		long long ans=0;
		for (node *p=pool+1;p!=poolnow;p++) ans+=(p->cnt+1ll)*p->cnt*(p->maxlen-p->p->maxlen);
		printf("%I64d\n", ans>>1);
	}
} SAM;
int main(){
	//freopen("ex.in", "r", stdin);
	scanf("%s", str+1), n=strlen(str+1), SAM.solve();
	return 0;
}


#include <cstdio>
#include <cstring>
inline unsigned int getuint(){
	char w=getchar();
	while (w<'0'||'9'<w) w=getchar();
	unsigned int ans=0;
	for (;'0'<=w&&w<='9';w=getchar()) ans=ans*10+w-'0';
	return ans;
}
int n;
char str[100005];
struct Suffix_AutoMaton{
	struct node{
		node *s[26], *p;
		int maxlen, cnt;
	} pool[100005<<1], *poolnow, *root;
	node *insert(node *p, int f){
		node *np=poolnow++;np->maxlen=p->maxlen+1;
		for (;p&&!p->s[f];p=p->p) p->s[f]=np;
		if (p)
			if (p->s[f]->maxlen!=p->maxlen+1){
				node *q=p->s[f], *nq=poolnow++;
				memcpy(nq->s, q->s, sizeof(q->s)), nq->p=q->p, nq->maxlen=p->maxlen+1, q->p=np->p=nq;
				for (;p&&p->s[f]==q;p=p->p) p->s[f]=nq;
			} else np->p=p->s[f];
		else np->p=root;
		return np;
	}
	int c[100005];
	node *a[100005<<1];
	void solve(){
		root=(poolnow=pool)++;
		node *last=root;
		for (int i=1;i<=n;i++) (last=insert(last, str[i]-'a'))->cnt=1;
		for (node *p=pool;p!=poolnow;p++) c[p->maxlen]++;
		for (int i=1;i<=n;i++) c[i]+=c[i-1];
		for (node *p=pool;p!=poolnow;p++) a[c[p->maxlen]--]=p;
		for (int i=poolnow-pool;i>1;i--) a[i]->p->cnt+=a[i]->cnt;
		root->cnt=0;
		long long ans=0;
		for (node *p=pool+1;p!=poolnow;p++) ans+=(p->cnt+1ll)*p->cnt*(p->maxlen-p->p->maxlen);
		printf("%I64d\n", ans>>1);
	}
} SAM;
int main(){
	//freopen("ex.in", "r", stdin);
	scanf("%s", str+1), n=strlen(str+1), SAM.solve();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100005;

string s;
int sa[maxn], rank[maxn], height[maxn];
int fir[maxn], sec[maxn], sum[maxn];
int n;

void Read () {
	cin >> s;
	n = s.size();
	s = " " + s;
}

void BuildSA () {
	int k = 0, m = 200, *x = rank, *y = sec;
	for (int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
	for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
	for (int i = n; i > 0; i--) sa[sum[x[i]]--] = i;
	for (int j = 1; k < n; j <<= 1, m = k) {
		k = 0;
		for (int i = n - j + 1; i <= n; i++) y[++k] = i;
		for (int i = 1; i <= n; i++) if (sa[i] > j) y[++k] = sa[i] - j;
		memset(sum, 0, 4 * (m + 1));
		for (int i = 1; i <= n; i++) fir[i] = x[y[i]];
		for (int i = 1; i <= n; i++) sum[fir[i]]++;
		for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
		for (int i = n; i > 0; i--) sa[sum[fir[i]]--] = y[i];
		swap(x, y); x[sa[1]] = 1; k = 1;
		for (int i = 2; i <= n; i++) {
			int a = sa[i - 1], b = sa[i];
			x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? k : ++k;
		}
	}
	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
	height[1] = 0; k = 0;
	for (int i = 1; i <= n; i++) if (rank[i] > 1) {
		if (k) k--; int j = sa[rank[i] - 1];
		while(s[i + k] == s[j + k]) k++;
		height[rank[i]] = k;
	}
}

int q[maxn];

long long Calc (long long x) {
	return x * (x + 1) / 2;
}

void Work () {
	long long ans = 0;
	int l = 1, r = 0;
	for (int i = 1; i <= n + 1; i++) {
		while (l <= r && height[i] < height[q[r]]) {
			ans += Calc(i - q[r] + 1) * (height[q[r]] - height[q[r - 1]]);
			r--;
		}
		if (l > r || height[i] > height[q[r]]) q[++r] = i;
	}
	for (int i = 1; i <= n; i++) ans += n - sa[i] + 1 - max(height[i], height[i + 1]);
	printf("%I64d\n", ans);
}

void Solve () {
	BuildSA();
	Work();
}

int main () {
	Read();
	Solve();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100005;

char s[maxn];
int sa[maxn], rank[maxn], height[maxn];
int fir[maxn], sec[maxn], sum[maxn];
int n;

void Read () {
	scanf("%s", s + 1);
	n = strlen(s + 1);
}

void BuildSA () {
	int k = 0, m = 200, *x = rank, *y = sec;
	for (int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
	for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
	for (int i = n; i > 0; i--) sa[sum[x[i]]--] = i;
	for (int j = 1; k < n; j <<= 1, m = k) {
		k = 0;
		for (int i = n - j + 1; i <= n; i++) y[++k] = i;
		for (int i = 1; i <= n; i++) if (sa[i] > j) y[++k] = sa[i] - j;
		memset(sum, 0, 4 * (m + 1));
		for (int i = 1; i <= n; i++) fir[i] = x[y[i]];
		for (int i = 1; i <= n; i++) sum[fir[i]]++;
		for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
		for (int i = n; i > 0; i--) sa[sum[fir[i]]--] = y[i];
		swap(x, y); x[sa[1]] = 1; k = 1;
		for (int i = 2; i <= n; i++) {
			int a = sa[i - 1], b = sa[i];
			x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? k : ++k;
		}
	}
	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
	height[1] = 0; k = 0;
	for (int i = 1; i <= n; i++) if (rank[i] > 1) {
		if (k) k--; int j = sa[rank[i] - 1];
		while(s[i + k] == s[j + k]) k++;
		height[rank[i]] = k;
	}
}

int q[maxn];

long long Calc (long long x) {
	return x * (x + 1) / 2;
}

void Work () {
	long long ans = 0;
	int l = 1, r = 0;
	for (int i = 1; i <= n + 1; i++) {
		while (l <= r && height[i] < height[q[r]])
			ans += Calc(i - q[r] + 1) * (height[q[r]] - height[q[--r]]);
		if (l > r || height[i] > height[q[r]]) q[++r] = i;
	}
	for (int i = 1; i <= n; i++) ans += n - sa[i] + 1 - max(height[i], height[i + 1]);
	cout << ans << endl;
}

void Solve () {
	BuildSA();
	Work();
}

int main () {
	Read();
	Solve();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100005;

char s[maxn];
int sa[maxn], rank[maxn], height[maxn];
int fir[maxn], sec[maxn], sum[maxn];
int n;

void Read () {
	scanf("%s", s + 1);
	n = strlen(s + 1);
}

void BuildSA () {
	int k = 0, m = 200, *x = rank, *y = sec;
	for (int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
	for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
	for (int i = n; i > 0; i--) sa[sum[x[i]]--] = i;
	for (int j = 1; k < n; j <<= 1, m = k) {
		k = 0;
		for (int i = n - j + 1; i <= n; i++) y[++k] = i;
		for (int i = 1; i <= n; i++) if (sa[i] > j) y[++k] = sa[i] - j;
		memset(sum, 0, 4 * (m + 1));
		for (int i = 1; i <= n; i++) fir[i] = x[y[i]];
		for (int i = 1; i <= n; i++) sum[fir[i]]++;
		for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
		for (int i = n; i > 0; i--) sa[sum[fir[i]]--] = y[i];
		swap(x, y); x[sa[1]] = 1; k = 1;
		for (int i = 2; i <= n; i++) {
			int a = sa[i - 1], b = sa[i];
			x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? k : ++k;
		}
	}
	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
	height[1] = 0; k = 0;
	for (int i = 1; i <= n; i++) if (rank[i] > 1) {
		if (k) k--; int j = sa[rank[i] - 1];
		while(s[i + k] == s[j + k]) k++;
		height[rank[i]] = k;
	}
}

int q[maxn];

long long Calc (long long x) {
	return x * (x + 1) / 2;
}

void Work () {
	long long ans = 0;
	int l = 1, r = 0;
	for (int i = 1; i <= n + 1; i++) {
		while (l <= r && height[i] < height[q[r]]) {
			ans += Calc(i - q[r] + 1) * (height[q[r]] - height[i]);
			r--;
		}
		if (l > r || height[i] > height[q[r]]) q[++r] = i;
	}
	for (int i = 1; i <= n; i++) ans += n - sa[i] + 1 - max(height[i], height[i + 1]);
	printf("%I64d\n", ans);
}

void Solve () {
	BuildSA();
	Work();
}

int main () {
	Read();
	Solve();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100005;

char s[maxn];
int sa[maxn], rank[maxn], height[maxn];
int fir[maxn], sec[maxn], sum[maxn];
int n;

void Read () {
	scanf("%s", s + 1);
	n = strlen(s + 1);
}

void BuildSA () {
	int k = 0, m = 200, *x = rank, *y = sec;
	for (int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
	for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
	for (int i = n; i > 0; i--) sa[sum[x[i]]--] = i;
	for (int j = 1; k < n; j <<= 1, m = k) {
		k = 0;
		for (int i = n - j + 1; i <= n; i++) y[++k] = i;
		for (int i = 1; i <= n; i++) if (sa[i] > j) y[++k] = sa[i] - j;
		memset(sum, 0, 4 * (m + 1));
		for (int i = 1; i <= n; i++) fir[i] = x[y[i]];
		for (int i = 1; i <= n; i++) sum[fir[i]]++;
		for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
		for (int i = n; i > 0; i--) sa[sum[fir[i]]--] = y[i];
		swap(x, y); x[sa[1]] = 1; k = 1;
		for (int i = 2; i <= n; i++) {
			int a = sa[i - 1], b = sa[i];
			x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? k : ++k;
		}
	}
	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
	height[1] = 0; k = 0;
	for (int i = 1; i <= n; i++) if (rank[i] > 1) {
		if (k) k--; int j = sa[rank[i] - 1];
		while(s[i + k] == s[j + k]) k++;
		height[rank[i]] = k;
	}
}

int q[maxn];

long long Calc (long long x) {
	return x * (x + 1) / 2;
}

void Work () {
	long long ans = 0;
	int l = 1, r = 0;
	for (int i = 1; i <= n + 1; i++) {
		while (l <= r && height[i] < height[q[r]])
			ans += Calc(i - q[r] + 1) * (height[q[r]] - height[q[--r]]);
		if (l > r || height[i] > height[q[r]]) q[++r] = i;
	}
	for (int i = 1; i <= n; i++) ans += n - sa[i] + 1 - max(height[i], height[i + 1]);
	printf("%I64d\n", ans);
}

void Solve () {
	BuildSA();
	Work();
}

int main () {
	Read();
	Solve();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100005;

char s[maxn];
int sa[maxn], rank[maxn], height[maxn];
int fir[maxn], sec[maxn], sum[maxn];
int n;

void Read () {
	scanf("%s", s + 1);
	n = strlen(s + 1);
}

void BuildSA () {
	int k = 0, m = 200, *x = rank, *y = sec;
	for (int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
	for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
	for (int i = n; i > 0; i--) sa[sum[x[i]]--] = i;
	for (int j = 1; k < n; j <<= 1, m = k) {
		k = 0;
		for (int i = n - j + 1; i <= n; i++) y[++k] = i;
		for (int i = 1; i <= n; i++) if (sa[i] > j) y[++k] = sa[i] - j;
		memset(sum, 0, 4 * (m + 1));
		for (int i = 1; i <= n; i++) fir[i] = x[y[i]];
		for (int i = 1; i <= n; i++) sum[fir[i]]++;
		for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
		for (int i = n; i > 0; i--) sa[sum[fir[i]]--] = y[i];
		swap(x, y); x[sa[1]] = 1; k = 1;
		for (int i = 2; i <= n; i++) {
			int a = sa[i - 1], b = sa[i];
			x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? k : ++k;
		}
	}
	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
	height[1] = 0; k = 0;
	for (int i = 1; i <= n; i++) if (rank[i] > 1) {
		if (k) k--; int j = sa[rank[i] - 1];
		while(s[i + k] == s[j + k]) k++;
		height[rank[i]] = k;
	}
}

int q[maxn];

long long Calc (long long x) {
	return x * (x + 1) / 2;
}

void Work () {
	long long ans = 0;
	int l = 1, r = 0;
	for (int i = 1; i <= n + 1; i++) {
		while (l <= r && height[i] < height[q[r]])
			ans += Calc(i - q[r] + 1) * (height[q[r]] - height[q[--r]]);
		if (l > r || height[i] > height[q[r]]) q[++r] = i;
	}
	for (int i = 1; i <= n; i++) ans += n - sa[i] + 1 - max(height[i], height[i + 1]);
	cout << endl;
}

void Solve () {
	BuildSA();
	Work();
}

int main () {
	Read();
	Solve();
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxn = 100005;

string s;
int sa[maxn], rank[maxn], height[maxn];
int fir[maxn], sec[maxn], sum[maxn];
int n;

void Read () {
	cin >> s;
	n = s.size();
	s = " " + s;
}

void BuildSA () {
	int k = 0, m = 200, *x = rank, *y = sec;
	for (int i = 1; i <= n; i++) sum[x[i] = s[i]]++;
	for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
	for (int i = n; i > 0; i--) sa[sum[x[i]]--] = i;
	for (int j = 1; k < n; j <<= 1, m = k) {
		k = 0;
		for (int i = n - j + 1; i <= n; i++) y[++k] = i;
		for (int i = 1; i <= n; i++) if (sa[i] > j) y[++k] = sa[i] - j;
		memset(sum, 0, 4 * (m + 1));
		for (int i = 1; i <= n; i++) fir[i] = x[y[i]];
		for (int i = 1; i <= n; i++) sum[fir[i]]++;
		for (int i = 1; i <= m; i++) sum[i] += sum[i - 1];
		for (int i = n; i > 0; i--) sa[sum[fir[i]]--] = y[i];
		swap(x, y); x[sa[1]] = 1; k = 1;
		for (int i = 2; i <= n; i++) {
			int a = sa[i - 1], b = sa[i];
			x[b] = (y[a] == y[b] && y[a + j] == y[b + j]) ? k : ++k;
		}
	}
	for (int i = 1; i <= n; i++) rank[sa[i]] = i;
	height[1] = 0; k = 0;
	for (int i = 1; i <= n; i++) if (rank[i] > 1) {
		if (k) k--; int j = sa[rank[i] - 1];
		while(s[i + k] == s[j + k]) k++;
		height[rank[i]] = k;
	}
}

inline long long Calc (long long x) {
	return x * (x + 1) / 2;
}

int q[maxn];

void Work () {
	long long ans = 0;
	int top = 0;
	for (int i = 1; i <= n; i++) height[i] = height[i + 1];
	for (int i = 1; i <= n; i++) {
		ans += n - sa[i] + 1 - max(height[i], height[i - 1]);
		while (top > 1 && height[i] <= height[q[top - 1]]) {
			ans += Calc(i - q[top - 1]) * (height[q[top]] - height[q[top - 1]]);
			top--;
		}
		if (height[i] <= height[q[top]]) {
			ans += Calc(i - q[top - 1]) * (height[q[top]] - height[i]);
			top--;
		}
		q[++top] = i;
	}
	printf("%I64d\n", ans);
}

void Solve () {
	BuildSA();
	Work();
}

int main () {
	Read();
	Solve();
	return 0;
}


//In the name of Allah
//
//
//////////////////////
// Program:
// Written By Alireza Farhadi (LGM)
//////////////////////
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <climits>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <utility>
#include <vector>
#include <bitset>
#include <deque>
#include <iomanip>
#include <complex>
#include <fstream>
#include <sstream>
//#include <map>
//#include <list>

using namespace std;

#if ( _WIN32 || __WIN32__ )
    #define LLD "%I64d"
#else
    #define LLD "%lld"
#endif

#define show(x) cerr<<((#x))<<" = "<<((x))<<" "<<endl
#define bit(a,b) (((a)>>(b))&1)
#define gcd __gcd
#define endl '\n'
#define bcnt(x) ((__builtin_popcount(x)))
#define sz(x) ((int((x).size())))
#define sqr(x) ((((x))*((x))))

template<class T> inline void smn(T &a,const T &b){if(b<a) a=b;}
template<class T> inline void smx(T &a,const T &b){if(b>a) a=b;}
template<class T> inline T rev(const T & a){T _=a; reverse(_.begin(),_.end()); return _;}

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pie;

const double eps=1e-9;
const ld leps=1e-14;

const int MN=1000*100+1000,INF=(1u<<31)-1;
ll h[MN],pw[MN];
ll res;
ll sum[MN];
pie list[MN];
string s;
int n;
ll key=701;
ll hash(int s,int e)
{
	ll res=h[e];
	if (s!=0)
		res-=h[s-1]*pw[e-s+1];
	return res;
}
bool cmp(const pie & a,const pie & b)
{
	int fs=a.first,fl=a.second-a.first,bs=b.first,bl=b.second-b.first;
	int l=min(fl,bl);
	if (hash(fs,fs+l)==hash(bs,bs+l))
		return fl<bl;
	int mn=INF;
	int s=0,e=l;
	while (s<=e)
	{
		int m=(s+e)/2;
		if (hash(fs,fs+m)!=hash(bs,bs+m))
		{
			mn=min(mn,m);
			e=m-1;
		}
		else
			s=m+1;
	}
	return (::s[fs+mn])<(::s[bs+mn]);
}
bool cmp2(const pie & a,const pie & b)
{
	int fs=a.first,fl=a.second-a.first,bs=b.first,bl=b.second-b.first;
	int l=min(fl,bl);
	if (hash(fs,fs+l)==hash(bs,bs+l))
		return 1;
	return 0;
}
stack <pie> st;
#define len(x) ((x).second-(x).first+1)
ll cnt[MN];
void pop()
{
	int t=st.top().first;
	int l=len(st.top());
	st.pop();
	if (!st.empty())
		l-=len(st.top());
	res+=ll(l)*((cnt[t]*(cnt[t]+1))/2);
	if (!st.empty())
		cnt[st.top().first]+=cnt[t];
}
int main(int argc,char * argv[])
{
	ios_base::sync_with_stdio(false);
	cin>>s;
	n=sz(s);
	for (int i=0;i<n;i++)
		if (i==0)
			pw[i]=1,h[i]=s[i];
		else
			pw[i]=key*pw[i-1],h[i]=key*h[i-1]+s[i];
	for (int i=0;i<n;i++)
		list[i]=pie(i,n-1);
	sort(list,list+n,cmp);
	for (int i=0;i<n;i++)
	{
		while (!st.empty() && cmp2(st.top(),list[i])==0)
			pop();
		st.push(list[i]);
		cnt[list[i].first]=1;
	}
	while (!st.empty())
		pop();
	cout<<res<<endl;
	return 0;
}


//In the name of Allah
//
//
//////////////////////
// Program:
// Written By Alireza Farhadi (LGM)
//////////////////////
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <utility>
#include <vector>
#include <bitset>
#include <deque>
#include <iomanip>
#include <complex>
#include <fstream>
#include <sstream>
#include <map>
//#include <climits>
//#include <list>

using namespace std;

#if ( _WIN32 || __WIN32__ )
    #define LLD "%I64d"
#else
    #define LLD "%lld"
#endif

#define show(x) cerr<<((#x))<<" = "<<((x))<<" "<<endl
#define bit(a,b) (((a)>>(b))&1)
#define gcd __gcd
#define endl '\n'
#define bcnt(x) ((__builtin_popcount(x)))
#define sz(x) ((int((x).size())))
#define sqr(x) ((((x))*((x))))
#define fx(x) fixed<<setprecision(x)

template<class T> inline void smn(T &a,const T &b){if(b<a) a=b;}
template<class T> inline void smx(T &a,const T &b){if(b>a) a=b;}
template<class T> inline T rev(const T & a){T _=a; reverse(_.begin(),_.end()); return _;}

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pie;

const double eps=1e-9;
const ld leps=1e-14;
vector <pie> move;
int p[100];
int t[100];
int r[100];
int n;
void go(int now,int s,int e,bool last)
{
	if (now<=0) return ;
	if (t[now]==0)
	{
		go(now-1,s,e,last); return ;
	}
		if (last==0 || e!=2)
		{
			go(now-1,s,3-s-e,0);
			for (int i=0;i<t[now];i++)
				move.push_back(pie(s,e));
			r[now]^=1;
			go(now-1,3-s-e,e,0);
			return ;
		}
		if (r[now])
		{
			go(now-1,s,3-s-e,0);
			for (int i=0;i<t[now];i++)
				move.push_back(pie(s,e));
			r[now]^=1;
			go(now-1,3-s-e,e,1);
			return ;
		}
		if (t[now]==1)
		{
			t[now]--;
			go(now,s,3-s-e,0);
			move.push_back(pie(s,e));
			go(now,3-s-e,e,1);
		}
		else
		{
			go(now-1,s,e,0);
			for (int i=0;i<t[now];i++)
				move.push_back(pie(s,3-s-e));
			go(now-1,e,s,0);
			for (int i=0;i<t[now];i++)
				move.push_back(pie(3-s-e,e));
			go(now-1,s,e,1);
		}
}
int main(int argc,char * argv[])
{
	ios_base::sync_with_stdio(false);
	cin>>n;
	for (int i=0;i<n;i++)
	{
		int a;
		cin>>a;
		t[a]++;
	}
	go(20,0,2,1);
	cout<<move.size()<<endl;
	for (int i=0;i<move.size();i++)
		cout<<move[i].first+1<<" "<<move[i].second+1<<endl;
	return 0;
}


//In the name of Allah
//
//
//////////////////////
// Program:
// Written By Alireza Farhadi (LGM)
//////////////////////
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <utility>
#include <vector>
#include <bitset>
#include <deque>
#include <iomanip>
#include <complex>
#include <fstream>
#include <sstream>
#include <map>
//#include <climits>
//#include <list>

using namespace std;

#if ( _WIN32 || __WIN32__ )
    #define LLD "%I64d"
#else
    #define LLD "%lld"
#endif

#define show(x) cerr<<((#x))<<" = "<<((x))<<" "<<endl
#define bit(a,b) (((a)>>(b))&1)
#define gcd __gcd
#define endl '\n'
#define bcnt(x) ((__builtin_popcount(x)))
#define sz(x) ((int((x).size())))
#define sqr(x) ((((x))*((x))))
#define fx(x) fixed<<setprecision(x)

template<class T> inline void smn(T &a,const T &b){if(b<a) a=b;}
template<class T> inline void smx(T &a,const T &b){if(b>a) a=b;}
template<class T> inline T rev(const T & a){T _=a; reverse(_.begin(),_.end()); return _;}

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pie;

const double eps=1e-9;
const ld leps=1e-14;
const int MN=1000*100+1000;
ll res;
int suf[MN][20];
string s;
vector <int> m[MN];
int p[MN];
pie tmp[MN];
int dsu[MN];
int size[MN];
ll now;
int n;
int par(int a) { return dsu[a]==a?a:dsu[a]=par(dsu[a]);}
void un(int a,int b)
{
	a=par(a); b=par(b);
	if (a==b) return ;
	now-=(ll(size[b])*(size[b]+1))/2;
	now-=(ll(size[a])*(size[a]+1))/2;
	dsu[b]=a;
	size[a]+=size[b];
	now+=(ll(size[a])*(size[a]+1)/2);
}
int lcp(int a,int b)
{
	int res=0;
	for (int i=19;i>=0 && a<n && b<n;i--) if (a+(1<<i)<=n && b+(1<<i)<=n && suf[a][i]==suf[b][i])
		res+=(1<<i),a+=(1<<i),b+=(1<<i);
	return res;
}
int main(int argc,char * argv[])
{
	ios_base::sync_with_stdio(false);
	cin>>s;
	n=sz(s);
	for (int i=0;i<n;i++)
		suf[i][0]=(s[i]-'a'+1);
	ll base=max(n+1,30);
	for (int i=1;i<20;i++)
	{
		vector <pie> all;
		map<pie,int> mp;
		for (int j=0;j<n;j++) if (j+(1<<(i-1))<n)
			tmp[j]=pie(suf[j][i-1],suf[j+(1<<(i-1))][i-1]);
		else
			tmp[j]=pie(suf[j][i-1],0);
		for (int j=0;j<n;j++) all.push_back(tmp[j]);
		sort(all.begin(),all.end());
		all.resize(unique(all.begin(),all.end())-all.begin());
		for (int j=0;j<all.size();j++)
			mp[all[j]]=j+1;
		for (int j=0;j<n;j++)
			suf[j][i]=mp[tmp[j]];
	}
/*	for (int i=0;i<3;i++)
	{
		for (int j=0;j<n;j++)
			cerr<<suf[j][i]<<" ";
		cerr<<endl;
	}*/
	for (int i=0;i<n;i++)
		tmp[i]=pie(suf[i][19],i);
	sort(tmp,tmp+n);
	for (int i=0;i<n;i++)
		p[i]=tmp[i].second;
	for (int i=0;i<n-1;i++)
	{
		int t=lcp(p[i],p[i+1]);
	//	cerr<<s.substr(p[i],n)<<" -> "<<t<<endl;
		m[t].push_back(i);
	}
//	cerr<<s.substr(p[n-1],n)<<endl;
	for (int i=0;i<n;i++)
		dsu[i]=i,size[i]=1;
	now=n;
	for (int i=n;i>=1;i--)
	{
		for (int j=0;j<m[i].size();j++)
			un(m[i][j],m[i][j]+1);
//		cerr<<i<<" -> "<<now<<endl;
		res+=now;
	}
	for (int i=n;i>1;i--)
		res-=(i-1);
	cout<<res<<endl;
	return 0;
}


//In the name of Allah
//
//
//////////////////////
// Program:
// Written By Alireza Farhadi (LGM)
//////////////////////
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <utility>
#include <vector>
#include <bitset>
#include <deque>
#include <iomanip>
#include <complex>
#include <fstream>
#include <sstream>
#include <map>
//#include <climits>
//#include <list>

using namespace std;

#if ( _WIN32 || __WIN32__ )
    #define LLD "%I64d"
#else
    #define LLD "%lld"
#endif

#define show(x) cerr<<((#x))<<" = "<<((x))<<" "<<endl
#define bit(a,b) (((a)>>(b))&1)
#define gcd __gcd
#define endl '\n'
#define bcnt(x) ((__builtin_popcount(x)))
#define sz(x) ((int((x).size())))
#define sqr(x) ((((x))*((x))))
#define fx(x) fixed<<setprecision(x)

template<class T> inline void smn(T &a,const T &b){if(b<a) a=b;}
template<class T> inline void smx(T &a,const T &b){if(b>a) a=b;}
template<class T> inline T rev(const T & a){T _=a; reverse(_.begin(),_.end()); return _;}

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pie;

const double eps=1e-9;
const ld leps=1e-14;
const int MN=1000*100+1000;
ll res;
int suf[MN][20];
string s;
vector <int> m[MN];
int p[MN];
pie tmp[MN];
int dsu[MN];
int size[MN];
ll now;
int n;
int par(int a) { return dsu[a]==a?a:dsu[a]=par(dsu[a]);}
void un(int a,int b)
{
	a=par(a); b=par(b);
	if (a==b) return ;
	now-=(ll(size[b])*(size[b]+1))/2;
	now-=(ll(size[a])*(size[a]+1))/2;
	dsu[b]=a;
	size[a]+=size[b];
	now+=(ll(size[a])*(size[a]+1)/2);
}
int lcp(int a,int b)
{
	int res=0;
	for (int i=19;i>=0 && a<n && b<n;i--) if (suf[a][i]==suf[b][i])
		res+=(1<<i),a+=(1<<i),b+=(1<<i);
	return res;
}
int main(int argc,char * argv[])
{
	ios_base::sync_with_stdio(false);
	cin>>s;
	n=sz(s);
	for (int i=0;i<n;i++)
		suf[i][0]=(s[i]-'a'+1);
	for (int i=1;i<20;i++)
	{
		vector <pie> all;
		map<pie,int> mp;
		for (int j=0;j<n;j++) if (j+(1<<(i-1))<n)
			tmp[j]=pie(suf[j][i-1],suf[j+(1<<(i-1))][i-1]);
		else
			tmp[j]=pie(suf[j][i-1],0);
		for (int j=0;j<n;j++) all.push_back(tmp[j]);
		sort(all.begin(),all.end());
		all.resize(unique(all.begin(),all.end())-all.begin());
		for (int j=0;j<all.size();j++)
			mp[all[j]]=j+1;
		for (int j=0;j<n;j++)
			suf[j][i]=mp[tmp[j]];
	}
	for (int i=0;i<n;i++)
		tmp[i]=pie(suf[i][19],i);
	sort(tmp,tmp+n);
	for (int i=0;i<n;i++)
		p[i]=tmp[i].second;
	for (int i=0;i<n-1;i++)
	{
		int t=lcp(p[i],p[i+1]);
		m[t].push_back(i);
	}
	for (int i=0;i<n;i++)
		dsu[i]=i,size[i]=1;
	now=n;
	for (int i=n;i>=1;i--)
	{
		for (int j=0;j<m[i].size();j++)
			un(m[i][j],m[i][j]+1);
		res+=now;
	}
	for (int i=n;i>1;i--)
		res-=(i-1);
	cout<<res<<endl;
	return 0;
}


//In the name of Allah
//
//
//////////////////////
// Program:
// Written By Alireza Farhadi (LGM)
//////////////////////
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <cctype>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <utility>
#include <vector>
#include <bitset>
#include <deque>
#include <iomanip>
#include <complex>
#include <fstream>
#include <sstream>
#include <map>
//#include <climits>
//#include <list>

using namespace std;

#if ( _WIN32 || __WIN32__ )
    #define LLD "%I64d"
#else
    #define LLD "%lld"
#endif

#define show(x) cerr<<((#x))<<" = "<<((x))<<" "<<endl
#define bit(a,b) (((a)>>(b))&1)
#define gcd __gcd
#define endl '\n'
#define bcnt(x) ((__builtin_popcount(x)))
#define sz(x) ((int((x).size())))
#define sqr(x) ((((x))*((x))))
#define fx(x) fixed<<setprecision(x)

template<class T> inline void smn(T &a,const T &b){if(b<a) a=b;}
template<class T> inline void smx(T &a,const T &b){if(b>a) a=b;}
template<class T> inline T rev(const T & a){T _=a; reverse(_.begin(),_.end()); return _;}

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pie;

const double eps=1e-9;
const ld leps=1e-14;
const int MN=1000*100+1000;
ll res;
int suf[MN][20];
string s;
vector <int> m[MN];
int p[MN];
pie tmp[MN];
int dsu[MN];
int size[MN];
ll now;
int n;
int par(int a) { return dsu[a]==a?a:dsu[a]=par(dsu[a]);}
void un(int a,int b)
{
	a=par(a); b=par(b);
	if (a==b) return ;
	now-=(ll(size[b])*(size[b]+1))/2;
	now-=(ll(size[a])*(size[a]+1))/2;
	dsu[b]=a;
	size[a]+=size[b];
	now+=(ll(size[a])*(size[a]+1)/2);
}
int lcp(int a,int b)
{
	int res=0;
	for (int i=19;i>=0 && a<n && b<n;i--) if (a+(1<<i)<=n && b+(1<<i)<=n && suf[a][i]==suf[b][i])
		res+=(1<<i),a+=(1<<i),b+=(1<<i);
	return res;
}
int main(int argc,char * argv[])
{
	ios_base::sync_with_stdio(false);
	cin>>s;
	n=sz(s);
	for (int i=0;i<n;i++)
		suf[i][0]=(s[i]-'a'+1);
	ll base=max(n+1,30);
	for (int i=1;i<20;i++)
	{
		vector <ll> all;
		map<ll,int> mp;
		for (int j=0;j<n;j++) if (j+(1<<(i-1))<n)
			suf[j][i]=(suf[j][i-1]*base+suf[j+(1<<(i-1))][i-1]);
		else
			suf[j][i]=suf[j][i-1]*base;
		for (int j=0;j<n;j++) all.push_back(suf[j][i]);
		sort(all.begin(),all.end());
		all.resize(unique(all.begin(),all.end())-all.begin());
		for (int j=0;j<all.size();j++)
			mp[all[j]]=j+1;
		for (int j=0;j<n;j++)
			suf[j][i]=mp[suf[j][i]];
	}
/*	for (int i=0;i<3;i++)
	{
		for (int j=0;j<n;j++)
			cerr<<suf[j][i]<<" ";
		cerr<<endl;
	}*/
	for (int i=0;i<n;i++)
		tmp[i]=pie(suf[i][19],i);
	sort(tmp,tmp+n);
	for (int i=0;i<n;i++)
		p[i]=tmp[i].second;
	for (int i=0;i<n-1;i++)
	{
		int t=lcp(p[i],p[i+1]);
	//	cerr<<s.substr(p[i],n)<<" -> "<<t<<endl;
		m[t].push_back(i);
	}
//	cerr<<s.substr(p[n-1],n)<<endl;
	for (int i=0;i<n;i++)
		dsu[i]=i,size[i]=1;
	now=n;
	for (int i=n;i>=1;i--)
	{
		for (int j=0;j<m[i].size();j++)
			un(m[i][j],m[i][j]+1);
//		cerr<<i<<" -> "<<now<<endl;
		res+=now;
	}
	for (int i=n;i>1;i--)
		res-=(i-1);
	cout<<res<<endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>

#define MAXL 100100
#define MAXC 256
using namespace std;
int arr[3][MAXL], cnt[MAXL], mc[MAXC], h[MAXL], *a, *ta, *r, *tr, sz;
void sa_init(char *str, int len){
    a = arr[0], ta = arr[1], r = arr[2], sz = 0;
    for(int i=0;i<len;i++) ta[i] = str[i];
    sort(ta, ta + len);
    for(int i=1;i<=len;i++) if(ta[i] != ta[i-1] || i == len) cnt[ mc[ ta[i-1] ] = sz++ ] = i;
    for(int i=len-1;i>=0;i--) a[ --cnt[ r[i] = mc[ str[i] ]]] = i;
    for(int k=1;k<len && r[a[len-1]]<len-1;k<<=1){
        for(int i=0;i<len;i++) cnt[r[a[i]]] = i + 1;
        for(int i=len-1;i>=0;i--) if(a[i] >= k) ta[ --cnt[ r[a[i] - k] ] ] = a[i] - k;
        for(int i=len-k;i<len;i++) ta[ --cnt[r[i]] ] = i;
        tr = a, a = ta, tr[a[0]] = 0;
        for(int i=1;i<len;i++) tr[a[i]] = tr[a[i-1]] + (r[a[i]] != r[a[i-1]] || a[i-1]+k >= len || r[a[i]+k] != r[a[i-1]+k]);
        ta = r, r = tr;
    }
}
void h_init(char *str, int len){
    for(int i=0,d=0,j;i<len;i++){
        if(str[i] == '#' || r[i] == len-1) h[r[i]] = d = 0;
        else{
            if(d) d--;
            j = a[r[i] + 1];
            while(str[i+d] != '#' && str[j+d] != '#' && str[i+d] == str[j+d]) d++;
            h[r[i]] = d;
        }
    }
}
char str[MAXL];
int st[MAXL], ct[MAXL];
int main(){
    __int64 res;
    while(~scanf("%s",str)){
        int len = strlen(str);
        sa_init(str, len);
        h_init(str, len);
     //   for(int i=0;i<len;i++)printf("%d ",h[i]);puts("");
        res = 0;
        int top = 0, q = 0; int tt = 0;
        st[top] = 0;
        for(int i=0;i<len;i++){
            res += (len - a[i] - max(h[i],q));
            q = h[i];
            if(h[i] > st[top]){
                st[++top] = h[i];
                ct[top] = 1;
            }
            else if(h[i] == st[top]) ct[top]++;
            else{
                ct[top]++;
                while(st[top] != h[i]){
                //    printf("+= st[%d] = %d = %d \n", top, st[top], ct[top]);
                    res += (st[top] - max(h[i], st[top - 1])) * ct[top] * (ct[top] + 1) / 2;
               //     printf("st[top] = %d , ct[top] = %d , h[i] = %d\n",st[top],ct[top],h[i]);
               //     printf("st[top-1] = %d\n",st[top-1]);

                    if(st[top - 1] < h[i]){
                        st[top] = h[i];
                    }
                    else{
                        ct[top - 1] += ct[top];
                        st[top] = ct[top] = 0;
                        top--;
                 //       cout<<st[top]<<endl;
                    }
                }
            }
          //  cout<<i<<","<<res<<endl; system("pause");
        }
        printf("%I64d\n", res);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>

#define MAXL 100100
#define MAXC 256
using namespace std;
int arr[3][MAXL], cnt[MAXL], mc[MAXC], h[MAXL], *a, *ta, *r, *tr, sz;
void sa_init(char *str, int len){
    a = arr[0], ta = arr[1], r = arr[2], sz = 0;
    for(int i=0;i<len;i++) ta[i] = str[i];
    sort(ta, ta + len);
    for(int i=1;i<=len;i++) if(ta[i] != ta[i-1] || i == len) cnt[ mc[ ta[i-1] ] = sz++ ] = i;
    for(int i=len-1;i>=0;i--) a[ --cnt[ r[i] = mc[ str[i] ]]] = i;
    for(int k=1;k<len && r[a[len-1]]<len-1;k<<=1){
        for(int i=0;i<len;i++) cnt[r[a[i]]] = i + 1;
        for(int i=len-1;i>=0;i--) if(a[i] >= k) ta[ --cnt[ r[a[i] - k] ] ] = a[i] - k;
        for(int i=len-k;i<len;i++) ta[ --cnt[r[i]] ] = i;
        tr = a, a = ta, tr[a[0]] = 0;
        for(int i=1;i<len;i++) tr[a[i]] = tr[a[i-1]] + (r[a[i]] != r[a[i-1]] || a[i-1]+k >= len || r[a[i]+k] != r[a[i-1]+k]);
        ta = r, r = tr;
    }
}
void h_init(char *str, int len){
    for(int i=0,d=0,j;i<len;i++){
        if(str[i] == '#' || r[i] == len-1) h[r[i]] = d = 0;
        else{
            if(d) d--;
            j = a[r[i] + 1];
            while(str[i+d] != '#' && str[j+d] != '#' && str[i+d] == str[j+d]) d++;
            h[r[i]] = d;
        }
    }
}
char str[MAXL];
__int64 st[MAXL];
int main(){
    __int64 res;
    while(~scanf("%s",str)){
        int len = strlen(str);
        sa_init(str, len);
        h_init(str, len);
     //   for(int i=0;i<len;i++)printf("%d ",h[i]);puts("");
        res = 0;
        int top = 0, q = 0;
        for(int i=0;i<len;i++){
            res += (len - a[i] - max(h[i],q));
            q = h[i];
            if(h[i] > top){
                top = h[i];
                st[top] = 1;
            }
            else if(h[i] == top) st[top]++;
            else{
                st[top]++;
                while(top != h[i]){
                 //   printf("+= st[%d] = %d \n", top, st[top]);
                    res += st[top] * (st[top] + 1) / 2;
                    st[top - 1] += st[top];
                    st[top] = 0;
                    top--;
                }
            }
          //  cout<<i<<","<<res<<endl;
        }
        while(top != 0){
            res += st[top] * (st[top] + 1) / 2;
            st[top - 1] += st[top];
        }
        printf("%I64d\n", res);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>

#define MAXL 100100
#define MAXC 256
using namespace std;
int arr[3][MAXL], cnt[MAXL], mc[MAXC], h[MAXL], *a, *ta, *r, *tr, sz;
void sa_init(char *str, int len){
    a = arr[0], ta = arr[1], r = arr[2], sz = 0;
    for(int i=0;i<len;i++) ta[i] = str[i];
    sort(ta, ta + len);
    for(int i=1;i<=len;i++) if(ta[i] != ta[i-1] || i == len) cnt[ mc[ ta[i-1] ] = sz++ ] = i;
    for(int i=len-1;i>=0;i--) a[ --cnt[ r[i] = mc[ str[i] ]]] = i;
    for(int k=1;k<len && r[a[len-1]]<len-1;k<<=1){
        for(int i=0;i<len;i++) cnt[r[a[i]]] = i + 1;
        for(int i=len-1;i>=0;i--) if(a[i] >= k) ta[ --cnt[ r[a[i] - k] ] ] = a[i] - k;
        for(int i=len-k;i<len;i++) ta[ --cnt[r[i]] ] = i;
        tr = a, a = ta, tr[a[0]] = 0;
        for(int i=1;i<len;i++) tr[a[i]] = tr[a[i-1]] + (r[a[i]] != r[a[i-1]] || a[i-1]+k >= len || r[a[i]+k] != r[a[i-1]+k]);
        ta = r, r = tr;
    }
}
void h_init(char *str, int len){
    for(int i=0,d=0,j;i<len;i++){
        if(str[i] == '#' || r[i] == len-1) h[r[i]] = d = 0;
        else{
            if(d) d--;
            j = a[r[i] + 1];
            while(str[i+d] != '#' && str[j+d] != '#' && str[i+d] == str[j+d]) d++;
            h[r[i]] = d;
        }
    }
}
char str[MAXL];
int st[MAXL], ct[MAXL];
int main(){
    __int64 res;
    while(~scanf("%s",str)){
        int len = strlen(str);
        sa_init(str, len);
        h_init(str, len);
     //   for(int i=0;i<len;i++)printf("%d ",h[i]);puts("");
        res = 0;
        int top = 0, q = 0; int tt = 0;
        st[top] = 0;
        for(int i=0;i<len;i++){
            res += (len - a[i] - max(h[i],q));
            q = h[i];
            if(h[i] > st[top]){
                st[++top] = h[i];
                ct[top] = 1;
            }
            else if(h[i] == st[top]) ct[top]++;
            else{
                ct[top]++;
                while(st[top] != h[i]){
                //    printf("+= st[%d] = %d = %d \n", top, st[top], ct[top]);
                    res += 1LL * (st[top] - max(h[i], st[top - 1])) * ct[top] * (ct[top] + 1) / 2;
               //     printf("st[top] = %d , ct[top] = %d , h[i] = %d\n",st[top],ct[top],h[i]);
               //     printf("st[top-1] = %d\n",st[top-1]);

                    if(st[top - 1] < h[i]){
                        st[top] = h[i];
                    }
                    else{
                        ct[top - 1] += ct[top];
                        st[top] = ct[top] = 0;
                        top--;
                 //       cout<<st[top]<<endl;
                    }
                }
            }
          //  cout<<i<<","<<res<<endl; system("pause");
        }
        printf("%I64d\n", res);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <set>
#include <map>

#define MAXL 100100
#define MAXC 256
using namespace std;
int arr[3][MAXL], cnt[MAXL], mc[MAXC], h[MAXL], *a, *ta, *r, *tr, sz;
void sa_init(char *str, int len){
    a = arr[0], ta = arr[1], r = arr[2], sz = 0;
    for(int i=0;i<len;i++) ta[i] = str[i];
    sort(ta, ta + len);
    for(int i=1;i<=len;i++) if(ta[i] != ta[i-1] || i == len) cnt[ mc[ ta[i-1] ] = sz++ ] = i;
    for(int i=len-1;i>=0;i--) a[ --cnt[ r[i] = mc[ str[i] ]]] = i;
    for(int k=1;k<len && r[a[len-1]]<len-1;k<<=1){
        for(int i=0;i<len;i++) cnt[r[a[i]]] = i + 1;
        for(int i=len-1;i>=0;i--) if(a[i] >= k) ta[ --cnt[ r[a[i] - k] ] ] = a[i] - k;
        for(int i=len-k;i<len;i++) ta[ --cnt[r[i]] ] = i;
        tr = a, a = ta, tr[a[0]] = 0;
        for(int i=1;i<len;i++) tr[a[i]] = tr[a[i-1]] + (r[a[i]] != r[a[i-1]] || a[i-1]+k >= len || r[a[i]+k] != r[a[i-1]+k]);
        ta = r, r = tr;
    }
}
void h_init(char *str, int len){
    for(int i=0,d=0,j;i<len;i++){
        if(str[i] == '#' || r[i] == len-1) h[r[i]] = d = 0;
        else{
            if(d) d--;
            j = a[r[i] + 1];
            while(str[i+d] != '#' && str[j+d] != '#' && str[i+d] == str[j+d]) d++;
            h[r[i]] = d;
        }
    }
}
char str[MAXL];
__int64 st[MAXL], ct[MAXL];
int main(){
    __int64 res;
    while(~scanf("%s",str)){
        int len = strlen(str);
        sa_init(str, len);
        h_init(str, len);
     //   for(int i=0;i<len;i++)printf("%d ",h[i]);puts("");
        res = 0;
        int top = 0, q = 0; __int64 tt = 0;
        st[top] = 0;
        for(int i=0;i<len;i++){
            res += (len - a[i] - max(h[i],q));
            q = h[i];
            if(h[i] > st[top]){
                st[++top] = h[i];
                ct[top] = 1;
            }
            else if(h[i] == st[top]) ct[top]++;
            else{
                ct[top]++;
                while(st[top] != h[i]){
                  // printf("+= st[%d] = %d \n", top, ct[top]);
                    res += (st[top] - st[top - 1]) * ct[top] * (ct[top] + 1) / 2;
                    ct[top - 1] += ct[top];
                    ct[top] = 0;
                    top--;
                }
            }
          //  cout<<i<<","<<res<<endl;
        }
        printf("%I64d\n", res);
    }
    return 0;
}


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>
#include <cstring>
using namespace std;

string s;
int n,stp;
int f[100005][20];
vector< pair<int,int> > bucket[100005];
int pre[100005],rank[100005],sz[100005];
long long sum;

int root(int x) {
  if (x != pre[x]) pre[x] = root(pre[x]);
  return pre[x];
}

void connect(int u,int v) {
  u = root(u);  v = root(v);
  sum -= 1LL * sz[u] * (sz[u] + 1)/2;
  sum -= 1LL * sz[v] * (sz[v] + 1)/2;
  sum += 1LL * (sz[u] + sz[v]) * (sz[u] + sz[v] + 1)/2;
  if (rank[u] > rank[v]) {
    pre[v] = u;  sz[u] += sz[v];
  }
  else {
    pre[u] = v;  sz[v] += sz[u];
  }
  if (rank[u] == rank[v]) rank[v]++;
}

pair<int,int> L[100005];
int idx[100005];

bool cmp(int A,int B) {
  return L[A] < L[B];
}

int lcp(int u,int v) {
  int ret = 0;
  for (int i = stp - 1; i >= 0; i--)
    if (u + (1 << i) <= n && v + (1 << i) <= n && f[u][i] == f[v][i]) {
      u += (1 << i);
      v += (1 << i);
      ret += (1 << i);
    }
  return ret;
}

void suffixArray() {
  cin >> s;
  n = s.size();
  for (int i = 0; i < n; i++) f[i][0] = s[i];
  for (int j = 1; ; j++) {
    for (int i = 0; i < n; i++) {
      L[i].first = f[i][j - 1];
      L[i].second = (i + (1 << (j - 1)) < n) ? f[i + (1 << (j - 1))][j - 1] : -1;
      idx[i] = i;
    }
    sort(idx,idx + n,cmp);
    for (int i = 0; i < n; i++)
      f[idx[i]][j] = (i && L[idx[i]] == L[idx[i - 1]]) ? f[idx[i - 1]][j] : i;
    if ((1 << j) >= n) {
      stp = j + 1;  break;
    }
  }
  int order[100005];
  for (int i = 0; i < n; i++) order[f[i][stp - 1]] = i;
  for (int i = 1; i < n; i++) bucket[lcp(order[i],order[i - 1])].push_back(make_pair(order[i],order[i - 1]));
}

int main() {
  suffixArray();
  long long final = 0;
  sum = 0;
  for (int i = 0; i < n; i++) pre[i] = i,sz[i] = 1;
  for (int iter = n; iter; iter--) {
    sum++;
    for (int i = 0; i < bucket[iter].size(); i++)
      connect(bucket[iter][i].first,bucket[iter][i].second);
    final += sum;
  }
  cout << final << endl;
}


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>
#include <cstring>
using namespace std;

string s;
int n,stp;
int f[100005][20];
vector< pair<int,int> > bucket[100005];
int pre[100005],rank[100005],sz[100005];
long long sum;

int root(int x) {
  if (x != pre[x]) pre[x] = root(pre[x]);
  return pre[x];
}

void connect(int u,int v) {
  u = root(u);  v = root(v);
  sum -= 1LL * sz[u] * (sz[u] + 1)/2;
  sum -= 1LL * sz[v] * (sz[v] + 1)/2;
  sum += 1LL * (sz[u] + sz[v]) * (sz[u] + sz[v] + 1)/2;
  if (rank[u] > rank[v]) {
    pre[v] = u;  sz[u] += sz[v];
  }
  else {
    pre[u] = v;  sz[v] += sz[u];
  }
  if (rank[u] == rank[v]) rank[v]++;
}

struct element {
  pair<int,int> val;
  int idx;
};

bool cmp(element A,element B) {
  return A.val < B.val;
}

int lcp(int u,int v) {
  int ret = 0;
  for (int i = stp - 1; i >= 0; i--)
    if (u + (1 << i) <= n && v + (1 << i) <= n && f[u][i] == f[v][i]) {
      u += (1 << i);
      v += (1 << i);
      ret += (1 << i);
    }
  return ret;
}

void suffixArray() {
  cin >> s;
  n = s.size();
  for (int i = 0; i < n; i++) f[i][0] = s[i];
  for (int j = 1; ; j++) {
    if ((1 << j) > n) {
      stp = j;  break;
    }
    element L[100005];
    for (int i = 0; i < n; i++) {
      L[i].val.first = f[i][j - 1];
      L[i].val.second = (i + (1 << (j - 1)) < n) ? f[i + (1 << (j - 1))][j - 1] : -1;
      L[i].idx = i;
    }
    sort(L,L + n,cmp);
    for (int i = 0; i < n; i++)
      f[L[i].idx][j] = (i && L[i].val == L[i - 1].val) ? f[L[i - 1].idx][j] : i;
  }
  int order[100005];
  for (int i = 0; i < n; i++) order[f[i][stp - 1]] = i;
  for (int i = 1; i < n; i++) bucket[lcp(order[i],order[i - 1])].push_back(make_pair(order[i],order[i - 1]));
}

int main() {
  suffixArray();
  long long final = 0;
  sum = 0;
  for (int i = 0; i < n; i++) pre[i] = i,sz[i] = 1;
  for (int iter = n; iter; iter--) {
    sum++;
    for (int i = 0; i < bucket[iter].size(); i++)
      connect(bucket[iter][i].first,bucket[iter][i].second);
    final += sum;
  }
  cout << final << endl;
}


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>
#include <vector>
#include <cstring>
using namespace std;

string s;
int n,stp;
int f[100005][20];
vector< pair<int,int> > bucket[100005];
int pre[100005],rank[100005],sz[100005];
long long sum;

int root(int x) {
  if (x != pre[x]) pre[x] = root(pre[x]);
  return pre[x];
}

void connect(int u,int v) {
  u = root(u);  v = root(v);
  sum -= 1LL * sz[u] * (sz[u] + 1)/2;
  sum -= 1LL * sz[v] * (sz[v] + 1)/2;
  sum += 1LL * (sz[u] + sz[v]) * (sz[u] + sz[v] + 1)/2;
  if (rank[u] > rank[v]) {
    pre[v] = u;  sz[u] += sz[v];
  }
  else {
    pre[u] = v;  sz[v] += sz[u];
  }
  if (rank[u] == rank[v]) rank[v]++;
}

pair<int,int> L[100005];
int idx[100005];

bool cmp(int A,int B) {
  return L[A] < L[B];
}

int lcp(int u,int v) {
  int ret = 0;
  for (int i = stp - 1; i >= 0; i--)
    if (u + (1 << i) <= n && v + (1 << i) <= n && f[u][i] == f[v][i]) {
      u += (1 << i);
      v += (1 << i);
      ret += (1 << i);
    }
  return ret;
}

void suffixArray() {
  cin >> s;
  n = s.size();
  for (int i = 0; i < n; i++) f[i][0] = s[i];
  for (int j = 1; ; j++) {
    if ((1 << j) > n) {
      stp = j;  break;
    }
    for (int i = 0; i < n; i++) {
      L[i].first = f[i][j - 1];
      L[i].second = (i + (1 << (j - 1)) < n) ? f[i + (1 << (j - 1))][j - 1] : -1;
      idx[i] = i;
    }
    sort(idx,idx + n,cmp);
    for (int i = 0; i < n; i++)
      f[idx[i]][j] = (i && L[idx[i]] == L[idx[i - 1]]) ? f[idx[i - 1]][j] : i;
  }
  int order[100005];
  for (int i = 0; i < n; i++) order[f[i][stp - 1]] = i;
  for (int i = 1; i < n; i++) bucket[lcp(order[i],order[i - 1])].push_back(make_pair(order[i],order[i - 1]));
}

int main() {
  suffixArray();
  long long final = 0;
  sum = 0;
  for (int i = 0; i < n; i++) pre[i] = i,sz[i] = 1;
  for (int iter = n; iter; iter--) {
    sum++;
    for (int i = 0; i < bucket[iter].size(); i++)
      connect(bucket[iter][i].first,bucket[iter][i].second);
    final += sum;
  }
  cout << final << endl;
}


#include<iostream>
#include<stack>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<map>
#include<numeric>
#include<sstream>
#include<cmath>
using namespace std;
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pb push_back
#define f(i,x,y) for(int i = x; i<y; i++ )
#define FOR(it,A) for(typeof A.begin() it = A.begin(); it!= A.end(); it++)
#define quad(x) (x) * (x)
#define mp make_pair
#define clr(x, y) memset(x, y, sizeof x)
#define fst first
#define snd second
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
#define inf (1 << 30)
#define MAXN 150000

int n,t; //n es el tamanho de la cadena
int p[MAXN],r[MAXN],h[MAXN];
char s[MAXN];

bool comp(int i,int j){ return p[i+t] < p[j+t]; }

void suff_arr(){
   int bc[256];
	f(i,0,256) bc[i] = 0;
	f(i,0,n) ++bc[s[i]];
	f(i,1,256) bc[i] += bc[i-1];
	f(i,0,n) r[--bc[s[i]]] = i;
	f(i,0,n) p[i] = bc[s[i]];
	for(t=1; t<n; t *= 2 ){
		for(int i = 0, j = 1; j<n; i = j++ ){
			while( j<n && p[r[j]] == p[r[i]] ) j++;
			if( j-i==1 ) continue;
			int *ini = r+i, *fin = r+j;
			sort(ini, fin, comp);
			int pri = p[*ini+t], num = i, pk;
			for(; ini<fin; p[*ini++] = num ){
				if(((pk=p[*ini+t]) == pri) || (i<=pri && pk<j) ){}
				else pri = pk, num = ini-r;
			}
		}
	}
}
void lcp() {
   int tam = 0, i, j;
   for(i = 0; i < n; i++) if (p[i] > 0) {
  	j = r[p[i] - 1];
  	while(s[i + tam] == s[j + tam]) ++tam;
  	h[p[i] - 1] = tam;
  	if (tam > 0) --tam;
   }
   h[n - 1] = 0;
}
pii ss[200000];
int sz = 0;
ll C[200000];
int main(){
	scanf("%s", s);
   n = strlen(s);
   s[n++] = '$';
   suff_arr();
   lcp();
   ll res = 0;
   for(ll i = 0; i < 200000; i++) C[i] = i * (i + 1) / 2;

   ss[sz++] = mp(0, 0);
   f(i, 1, n){
      res += n - r[i] - 1 - max(h[i], h[i - 1]);
      while(ss[sz - 1].fst > h[i]){
         res += C[i - ss[sz - 1].snd + 1] * (ss[sz - 1].fst - max(h[i], ss[sz - 2].fst));
         sz--;
      }
      if(ss[sz - 1].fst != h[i])
         ss[sz++] = mp(h[i], i);
   }
   cout << res << endl;
}


#include<iostream>
#include<stack>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<map>
#include<numeric>
#include<sstream>
#include<cmath>
using namespace std;
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pb push_back
#define f(i,x,y) for(int i = x; i<y; i++ )
#define FOR(it,A) for(typeof A.begin() it = A.begin(); it!= A.end(); it++)
#define quad(x) (x) * (x)
#define mp make_pair
#define clr(x, y) memset(x, y, sizeof x)
#define fst first
#define snd second
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
#define inf (1 << 30)
#define MAXN 150000

int n,t; //n es el tamanho de la cadena
int p[MAXN],r[MAXN],h[MAXN];
char s[MAXN];

bool comp(int i,int j){ return p[i+t] < p[j+t]; }

void suff_arr(){
   int bc[256];
	f(i,0,256) bc[i] = 0;
	f(i,0,n) ++bc[s[i]];
	f(i,1,256) bc[i] += bc[i-1];
	f(i,0,n) r[--bc[s[i]]] = i;
	f(i,0,n) p[i] = bc[s[i]];
	for(t=1; t<n; t *= 2 ){
		for(int i = 0, j = 1; j<n; i = j++ ){
			while( j<n && p[r[j]] == p[r[i]] ) j++;
			if( j-i==1 ) continue;
			int *ini = r+i, *fin = r+j;
			sort(ini, fin, comp);
			int pri = p[*ini+t], num = i, pk;
			for(; ini<fin; p[*ini++] = num ){
				if(((pk=p[*ini+t]) == pri) || (i<=pri && pk<j) ){}
				else pri = pk, num = ini-r;
			}
		}
	}
}
void lcp() {
   int tam = 0, i, j;
   for(i = 0; i < n; i++) if (p[i] > 0) {
  	j = r[p[i] - 1];
  	while(s[i + tam] == s[j + tam]) ++tam;
  	h[p[i] - 1] = tam;
  	if (tam > 0) --tam;
   }
   h[n - 1] = 0;
}
pii ss[200000];
int sz = 0;
ll C[200000];
int main(){
	scanf("%s", s);
   n = strlen(s);
   s[n++] = '$';
   suff_arr();
   lcp();
   ll res = 0;
   for(ll i = 0; i < 200000; i++) C[i] = i * (i + 1) / 2;

   ss[sz++] = mp(0, 0);
   f(i, 1, n){
      res += n - r[i] - 1 - max(h[i], h[i - 1]);
      while(ss[sz - 1].fst > h[i])
         if(h[i] <= ss[sz - 2].fst){
            res += C[i - ss[sz - 1].snd + 1] * (ss[sz - 1].fst - ss[sz - 2].fst);
            sz--;
         }else{
            res += C[i - ss[sz - 1].snd + 1] * (ss[sz - 1].fst - h[i]);
            ss[sz - 1].fst = h[i];
         }

      if(ss[sz - 1].fst != h[i])
         ss[sz++] = mp(h[i], i);
   }
   cout << res << endl;
}


#include<iostream>
#include<stack>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<map>
#include<numeric>
#include<sstream>
#include<cmath>
using namespace std;
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pb push_back
#define f(i,x,y) for(int i = x; i<y; i++ )
#define FOR(it,A) for(typeof A.begin() it = A.begin(); it!= A.end(); it++)
#define quad(x) (x) * (x)
#define mp make_pair
#define clr(x, y) memset(x, y, sizeof x)
#define fst first
#define snd second
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
#define inf (1 << 30)
#define MAXN 150000

int n,t; //n es el tamanho de la cadena
int p[MAXN],r[MAXN],h[MAXN];
char s[MAXN];

bool comp(int i,int j){ return p[i+t] < p[j+t]; }

void suff_arr(){
   int bc[256];
	f(i,0,256) bc[i] = 0;
	f(i,0,n) ++bc[s[i]];
	f(i,1,256) bc[i] += bc[i-1];
	f(i,0,n) r[--bc[s[i]]] = i;
	f(i,0,n) p[i] = bc[s[i]];
	for(t=1; t<n; t *= 2 ){
		for(int i = 0, j = 1; j<n; i = j++ ){
			while( j<n && p[r[j]] == p[r[i]] ) j++;
			if( j-i==1 ) continue;
			int *ini = r+i, *fin = r+j;
			sort(ini, fin, comp);
			int pri = p[*ini+t], num = i, pk;
			for(; ini<fin; p[*ini++] = num ){
				if(((pk=p[*ini+t]) == pri) || (i<=pri && pk<j) ){}
				else pri = pk, num = ini-r;
			}
		}
	}
}
void lcp() {
   int tam = 0, i, j;
   for(i = 0; i < n; i++) if (p[i] > 0) {
  	j = r[p[i] - 1];
  	while(s[i + tam] == s[j + tam]) ++tam;
  	h[p[i] - 1] = tam;
  	if (tam > 0) --tam;
   }
   h[n - 1] = 0;
}
pii ss[200000];
int sz = 0;
ll C[200000];
int main(){
	scanf("%s", s);
   n = strlen(s);
   s[n++] = '$';
   suff_arr();
   lcp();
   ll res = 0;
   for(ll i = 0; i < 200000; i++) C[i] = i * (i + 1) / 2;

   ss[sz++] = mp(0, 0);
   f(i, 1, n){
      res += n - r[i] - 1 - max(h[i], h[i - 1]);
      while(ss[sz - 1].fst > h[i]){
         res += C[i - ss[sz - 1].snd + 1] * (ss[sz - 1].fst - ss[sz - 2].fst);
         sz--;
      }
      if(ss[sz - 1].fst != h[i])
         ss[sz++] = mp(h[i], i);
   }
   cout << res << endl;
}


#include<cassert>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<set>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<numeric>
#include<climits>
#include<sstream>
#include<cmath>
using namespace std;
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define pb push_back
#define f(i,x,y) for(int i = x; i<y; i++)
#define FOR(it,A) for(typeof A.begin() it = A.begin(); it!= A.end(); it++)
#define quad(x) (x) * (x)
#define mp make_pair
#define clr(x, y) memset(x, y, sizeof x)
#define fst first
#define snd second
typedef pair<int, int> pii;
typedef long long ll;
typedef long double ld;
#define MAXN 100009
int n,t; //n es el tamanho de la cadena
int p[MAXN],r[MAXN],h[MAXN];
string s;

bool comp(int i,int j){ return p[i+t] < p[j+t]; }

void suff_arr(){
    int bc[256];
    f(i,0,256) bc[i] = 0;
    f(i,0,n) ++bc[s[i]];
    f(i,1,256) bc[i] += bc[i-1];
    f(i,0,n) r[--bc[s[i]]] = i;
    f(i,0,n) p[i] = bc[s[i]];
    for(t=1; t<n; t *= 2 ){
        for(int i = 0, j = 1; j<n; i = j++ ){
            while( j<n && p[r[j]] == p[r[i]] ) j++;
            if( j-i==1 ) continue;
            int *ini = r+i, *fin = r+j;
            sort(ini, fin, comp);
            int pri = p[*ini+t], num = i, pk;
            for(; ini<fin; p[*ini++] = num ){
                if(((pk=p[*ini+t]) == pri) || (i<=pri && pk<j) ){}
                else pri = pk, num = ini-r;
            }
        }
    }
}
void lcp() {
    int tam = 0, i, j;
    for(i = 0; i < n; i++) if (p[i] > 0) {
        j = r[p[i] - 1];
        while(s[i + tam] == s[j + tam]) ++tam;
        h[p[i] - 1] = tam;
        if (tam > 0) --tam;
    }
    h[n - 1] = 0;
}
pii ss[MAXN]; int sz = 0;
int main(){
    ios::sync_with_stdio(false);
    cin >> s;
    s += '$';
    n = s.size();
    suff_arr();
    lcp();
    ll total = 0, res = 0;
    f(i, 1, n){
        total += n - 1 - r[i];
        res += total;
        ll muertos = 0, veces = 0;
        ss[sz++] = mp(n - 1 - r[i], 1);
        while(sz > 0 && ss[sz - 1].fst >= h[i]){
            muertos += (ss[sz - 1].fst - h[i]) * ll(ss[sz - 1].snd);
            veces += ss[sz - 1].snd;
            sz--;
        }
        total -= muertos;
        if(h[i]) ss[sz++] = mp(h[i], veces);
    }
    cout << res << endl;
}


#include<bits/stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
typedef long long LL;
using namespace std;
const int MAXN=100005;
const int SIGMA_SIZE=26;

typedef long long int ll;

struct SAM{
    int n,st;
    //1为初始状态，2到n为保存了子串信息的所有状态
    //maxlen表示每个状态对应的子串中长度最大值，minlen最小值
    //trans是转移边，根节点是1，所以0代表不存在
    //slink表示绿色的suffix link
    //col表示节点颜色，col=1代表是后缀节点，=0代表不是后缀的节点
    //indeg表示对于只含有suffix link的图的度，统计endposamu用
    //endposa表示该状态对应的子串们出现的结尾位置，amu表示endpos集合的大小
    int maxlen[2*MAXN+10],minlen[2*MAXN+10],trans[2*MAXN+10][SIGMA_SIZE],slink[2*MAXN+10],
        col[2*MAXN+10],indeg[2*MAXN+10],endposamu[2*MAXN+10];

    int new_state(int _maxlen, int _minlen, int* _trans, int _slink){
        n++;
        maxlen[n]=_maxlen;
        minlen[n]=_minlen;
        for(int i=0; i<SIGMA_SIZE; i++){
            if(_trans==NULL)
                trans[n][i]=0;
            else
                trans[n][i]=_trans[i];
        }
        slink[n]=_slink;
        return n;
    }

    int add_char(char ch, int u){
        int c=ch-'a';
        int z=new_state(maxlen[u]+1, -1, NULL, 0);
        col[z]=1;
        int v=u;
        while(v!=0&&trans[v][c]==0){
            trans[v][c]=z;
            v=slink[v];
        }
        if(v==0){
            minlen[z]=1;
            slink[z]=1;
            indeg[1]++;
            return z;
        }
        int x=trans[v][c];
        if(maxlen[v]+1==maxlen[x]){
            minlen[z]=maxlen[x]+1;
            slink[z]=x;
            indeg[x]++;
            return z;
        }
        int y=new_state(maxlen[v]+1, -1, trans[x], slink[x]);
        col[y]=0;

        minlen[x]=maxlen[y]+1;
        slink[x]=y;
        minlen[z]=maxlen[y]+1;
        slink[z]=y;
        indeg[y]+=2;
        int w=v;
        while(w!=0&&trans[w][c]==x){
            trans[w][c]=y;
            w=slink[w];
        }
        minlen[y]=maxlen[slink[y]]+1;
        return z;
    }
    void init(){
        memset(col, 0, sizeof(col));
        memset(indeg, 0, sizeof(indeg));
        memset(maxlen, 0, sizeof(maxlen));
        memset(minlen, 0, sizeof(maxlen));
        memset(trans, 0, sizeof(maxlen));
        memset(slink, 0, sizeof(maxlen));
        memset(endposamu, 0, sizeof(endposamu));
        n=0;
        st=new_state(0, -1, NULL, 0);
    }
    void getendpos(){
        queue<int> que;
        for(int i=st;i<=n;i++){
            if(indeg[i]==0) que.push(i);
            if(col[i]==1) endposamu[i]++;
        }
        while(!que.empty()){
            int pos=que.front();que.pop();
            endposamu[slink[pos]]+=endposamu[pos];
            indeg[slink[pos]]--;
            if(indeg[slink[pos]]==0) que.push(slink[pos]);
        }
    }
    void addstring(char* s,int n){
        int la=st;
        for(int i=0;i<n;i++)
            la=add_char(s[i], la);
        getendpos();
    }
    void solve(){
        ll res=0;
        for(int i=2;i<=n;i++){
            ll amount=maxlen[i]-minlen[i]+1;
            res+=amount*(endposamu[i]+1)*endposamu[i]/2;
        }
        printf("%I64d\n",res);
    }
}sam;

char str[MAXN*2+7];

int main(){
    sam.init();
    scanf("%s",str);
    int n=strlen(str);
    sam.addstring(str,n);
    sam.solve();
    return 0;
}


#include<bits/stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
typedef long long LL;
using namespace std;
const int MAXN=100005;
const int SIGMA_SIZE=26;

typedef long long int ll;

struct SAM{
    int n=0,st;
    //1为初始状态，2到n为保存了子串信息的所有状态
    //maxlen表示每个状态对应的子串中长度最大值，minlen最小值
    //trans是转移边，根节点是1，所以0代表不存在
    //slink表示绿色的suffix link
    //col表示节点颜色，col=1代表是后缀节点，=0代表不是后缀的节点
    //indeg表示对于只含有suffix link的图的度，统计endposamu用
    //endposa表示该状态对应的子串们出现的结尾位置，amu表示endpos集合的大小
    int maxlen[2*MAXN+10],minlen[2*MAXN+10],trans[2*MAXN+10][SIGMA_SIZE],slink[2*MAXN+10],
        col[2*MAXN+10],indeg[2*MAXN+10],endposamu[2*MAXN+10];

    int new_state(int _maxlen, int _minlen, int* _trans, int _slink){
        n++;
        maxlen[n]=_maxlen;
        minlen[n]=_minlen;
        for(int i=0; i<SIGMA_SIZE; i++){
            if(_trans==NULL)
                trans[n][i]=0;
            else
                trans[n][i]=_trans[i];
        }
        slink[n]=_slink;
        return n;
    }

    int add_char(char ch, int u){
        int c=ch-'a';
        int z=new_state(maxlen[u]+1, -1, NULL, 0);
        col[z]=1;
        int v=u;
        while(v!=0&&trans[v][c]==0){
            trans[v][c]=z;
            v=slink[v];
        }
        if(v==0){
            minlen[z]=1;
            slink[z]=1;
            indeg[1]++;
            return z;
        }
        int x=trans[v][c];
        if(maxlen[v]+1==maxlen[x]){
            minlen[z]=maxlen[x]+1;
            slink[z]=x;
            indeg[x]++;
            return z;
        }
        int y=new_state(maxlen[v]+1, -1, trans[x], slink[x]);
        col[y]=0;

        minlen[x]=maxlen[y]+1;
        slink[x]=y;
        minlen[z]=maxlen[y]+1;
        slink[z]=y;
        indeg[y]+=2;
        int w=v;
        while(w!=0&&trans[w][c]==x){
            trans[w][c]=y;
            w=slink[w];
        }
        minlen[y]=maxlen[slink[y]]+1;
        return z;
    }
    void init(){
        memset(col, 0, sizeof(col));
        memset(indeg, 0, sizeof(indeg));
        memset(maxlen, 0, sizeof(maxlen));
        memset(minlen, 0, sizeof(maxlen));
        memset(trans, 0, sizeof(maxlen));
        memset(slink, 0, sizeof(maxlen));
        memset(endposamu, 0, sizeof(endposamu));
        n=0;
        st=new_state(0, -1, NULL, 0);
    }
    void getendpos(){
        queue<int> que;
        for(int i=st;i<=n;i++){
            if(indeg[i]==0) que.push(i);
            if(col[i]==1) endposamu[i]++;
        }
        while(!que.empty()){
            int pos=que.front();que.pop();
            endposamu[slink[pos]]+=endposamu[pos];
            indeg[slink[pos]]--;
            if(indeg[slink[pos]]==0) que.push(slink[pos]);
        }
    }
    void addstring(char* s,int n){
        int la=st;
        for(int i=0;i<n;i++)
            la=add_char(s[i], la);
        getendpos();
    }
    void solve(){
        ll res=0;
        for(int i=2;i<=n;i++){
            ll amount=maxlen[i]-minlen[i]+1;
            res+=amount*(endposamu[i]+1)*endposamu[i]/2;
        }
        printf("%I64d\n",res);
    }
}sam;

char str[MAXN*2+7];

int main(){
    sam.init();
    scanf("%s",str);
    int n=strlen(str);
    sam.addstring(str,n);
    sam.solve();
    return 0;
}


#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#define FOR(i,a,b) for(i=a;i<=b; i++)
#define FOR2(i,n) FOR(i,0,n-1)
#define COMB(x) ( ( (long long)(x) * (long long)(x-1) ) / 2 )
#define f first
#define s second
#define BASE 1009ll
#define MAXN 100005
#define all(x) x.begin(),x.end()
using namespace std;
typedef pair < long long , int > pli;
class trial
{
	public:
		int f,s,x;
		trial() { f = s = x = 0; }
}P[MAXN];
inline trial make_trial(int a,int b,int c) { trial k; k.f = a; k.s = b; k.x = c; return k; }
pli ST[4*MAXN];
long long H[MAXN] , pow[MAXN];
int N,T;
int B[MAXN] , C[MAXN] , K[MAXN];
char A[MAXN];
inline bool cmp( const trial &a , const trial &b )
{
	if(a.f < b.f) return true;
	if(a.f > b.f) return false;
	return a.s < b.s;
}
bool numaralandir()
{
	int i,j,s(0);
	sort(P+1,P+N+1,cmp);
	FOR(i,1,N)
	{
		s++;
		j = i;
		while(i <= N && P[i].f == P[j].f && P[i].s == P[j].s) B[ P[i++].x ] = s;
		i--;
	}
	return s == N;
}
void suffix_array()
{
	int cnt(1),i;
	FOR(i,1,N) P[i] = make_trial( A[i] , A[i] , i );

	while(1)
	{
		if(numaralandir()) return;

		FOR(i,1,N)
			P[i] = make_trial( B[i] , ( (i+cnt <= N) ? B[i+cnt] : 0 ) , i );

		cnt <<= 1;
	}
}
long long get(int a,int b)
{
	return H[b] - H[a-1] * pow[b-a+1];
}
int getlcp(int a,int b)
{
	int i,res(0);
	for(i = T; i >= 0; i--)
	{
		if(a + (1<<i) - 1 > N) continue;
		if(b + (1<<i) - 1 > N) continue;
		if( get(a , a + (1<<i) - 1) == get(b , b + (1<<i) - 1) )
		{
			a += (1<<i);
			b += (1<<i);
			res += (1<<i);
		}
	}
	return res;
}
void LCP()
{
	int i;
	pow[0] = 1;
	FOR(i,1,N)
	{
		H[i] = H[i-1] * BASE + A[i];
		pow[i] = pow[i-1] * BASE;
	}

	FOR(i,1,N-1)
		C[i] = getlcp(K[i],K[i+1]) + 1;
	C[N] = 1;
}
pli init(int pos,int s,int e)
{
	if(s == e) return ST[pos] = make_pair( C[s] , s );
	int m = ( s + e ) >> 1;
	int sol = pos << 1;
	int sag = sol | 1;
	pli p1 = init(sol,s,m);
	pli p2 = init(sag,m+1,e);
	return ST[pos] = (p1.f < p2.f) ? p1 : p2;
}
pli find(int pos,int s,int e,int a,int b)
{
	if(a > e || b < s) return make_pair( 1000000000000ll , 0 );
	if(a <= s && e <= b) return ST[pos];
	int m = ( s + e ) >> 1;
	int sol = pos << 1;
	int sag = sol | 1;
	pli p1 = find(sol,s,m,a,b);
	pli p2 = find(sag,m+1,e,a,b);
	return (p1.f < p2.f) ? p1 : p2;
}
long long dq(int a,int b,int k)
{
	if(a > b) return 0;
	pli p = find(1,1,N,a,b);

	long long s = COMB(b-a+2) * (p.f - k);
	return s + dq(a , p.s-1 , p.f ) + dq(p.s+1 , b , p.f);

}
void solve()
{
	int i;
	scanf("%s",A+1);
	N = strlen(A+1);
	while( (1 << T) < N ) T++;
	T--;

	suffix_array();

	FOR(i,1,N) K[ B[i] ] = i;

	LCP();

	init(1,1,N);

	printf("%lld\n" , dq(1,N,0) ) ;

}
int main()
{
//	freopen(".gir","r",stdin);
//	freopen(".cik","w",stdout);
	solve();
	return 0;
}