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

#define x first
#define y second
#define pb push_back
#define pf push_front
#define mp make_pair
#define LL long long
#define LD long double
#define ull unsigned long long
#define uint unsigned int
#define Pair pair<int,int>
#define pLL pair<LL,LL>
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define REP(i,a,b) for (int i=a;i>=b;i--)

const int MAXN=1e5;

char s[MAXN+48];int n;
stack<pLL> sta;

namespace Suffix_Array
{
    int cnt[MAXN+48],fir[MAXN+48],sec[MAXN+48],sa[MAXN+48],tmp[MAXN+48];
	int rnk[MAXN+48],lcp[MAXN+48];
	inline bool compare_sa(int x,int y,int k)
	{
		if (fir[x]!=fir[y]) return fir[x]<fir[y];
		int tmp1=(x+k<=n?fir[x+k]:-1),tmp2=(y+k<=n?fir[y+k]:-1);
		return tmp1<tmp2;
	}
	inline void construct_sa(char s[])
	{
		int maxind='z';memset(cnt+1,0,maxind<<2);
		for (register int i=1;i<=n;i++) cnt[s[i]]++;
		for (register int i=1;i<=maxind;i++) cnt[i]+=cnt[i-1];
		for (register int i=n;i>=1;i--) sa[cnt[s[i]]--]=i;
		fir[sa[1]]=1;for (register int i=2;i<=n;i++) fir[sa[i]]=fir[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);
		for (register int len=1;len<=n;len<<=1)
		{
			int tot=0;
			for (register int i=n-len+1;i<=n;i++) sec[++tot]=i;
			for (register int i=1;i<=n;i++) if (sa[i]>len) sec[++tot]=sa[i]-len;
			memset(cnt+1,0,maxind<<2);
			for (register int i=1;i<=n;i++) cnt[fir[sec[i]]]++;
			for (register int i=1;i<=maxind;i++) cnt[i]+=cnt[i-1];
			for (register int i=n;i>=1;i--) sa[cnt[fir[sec[i]]]--]=sec[i];
			tmp[sa[1]]=tot=1;
			for (register int i=2;i<=n;i++) tmp[sa[i]]=tmp[sa[i-1]]+compare_sa(sa[i-1],sa[i],len);
			memcpy(fir+1,tmp+1,n<<2);
			maxind=fir[sa[n]];if (maxind>=n) break;
		}
	}
	inline void construct_lcp()
	{
		int h=0;
		for (register int i=1;i<=n;i++) rnk[sa[i]]=i;
		for (register int i=1;i<=n;i++)
		{
			int j=sa[rnk[i]-1];
			if (h) h--;
			while (i+h<=n && j+h<=n && s[i+h]==s[j+h]) h++;
			lcp[rnk[i]-1]=h;
		}
	}
}

int main ()
{
#ifndef ONLINE_JUDGE
    double T=clock();
    freopen ("a.in","r",stdin);
    freopen ("a.out","w",stdout);
    cerr<<"Running..."<<endl;
#endif
    scanf("%s",s+1);n=strlen(s+1);
    using namespace Suffix_Array;
    construct_sa(s);construct_lcp();
    LL ans=1ll*(n+1)*n/2,curans=0,curcnt;
    REP(i,n-1,1)
    {
        curcnt=1;
        while (!sta.empty() && lcp[i]<sta.top().x) curcnt+=sta.top().y,curans-=sta.top().x*sta.top().y,sta.pop();
        curans+=1ll*lcp[i]*curcnt;ans+=curans;sta.push(mp(lcp[i],curcnt));
    }
    printf("%lld\n",ans);
#ifndef ONLINE_JUDGE
    cerr<<"Exec Time: "<<(clock()-T)/CLOCKS_PER_SEC<<endl;
#endif
    return 0;
}


#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
//#pragma GCC optimize("Ofast,no-stack-protector")
#define int long long
//#define ull signed long long
#define mm 100007
//#define N 500008
//#define M 2000007
#define oo 1000000000000
//#define ll long long
//ios::sync_with_stdio(false);
#define mod 998244353

using namespace std;
const double eps=1e-7;

int head[mm];
//struct edge
//{
//    int to;int next;
//}e[mm];
struct edge
{
    int to;int next;
}e[mm<<1];
int inde=0;
void add(int u,int v)
{
    e[++inde].to=v;
    e[inde].next=head[u];
    head[u]=inde;
}
///////////////////////////////
char s[mm];
int ans=0;
int len[mm];int ch[mm][26];int siz[mm];
int now=1;int fa[mm];
int tot=1;
void in(int c)
{
    int p=now;
    int id=now=++tot;
    siz[tot]=1;
    len[id]=len[p]+1;
    for(;p&&!ch[p][c];p=fa[p]){ch[p][c]=id;}
    if(!p){fa[id]=1;}
    else{
        int q=ch[p][c];
        if(len[q]==len[p]+1){fa[id]=q;}
        else{
            int idi=++tot;
            fa[idi]=fa[q];len[idi]=len[p]+1;
            for(int i=0;i<26;i++){ch[idi][i]=ch[q][i];}
            fa[q]=fa[id]=idi;
            for(;p&&ch[p][c]==q;p=fa[p]){ch[p][c]=idi;}
        }
    }
}

void dfs(int x)
{
    for(int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        dfs(v);
        siz[x]+=siz[v];
    }
}

signed main()
{
    scanf("%s",s+1);
    for(int i=1;i<=strlen(s+1);i++)
    {
        int tmp=s[i]-'a';
        in(tmp);
    }
//    for(int i=tot;i>1;i--)
//    {
//        siz[fa[i]]+=siz[i];
//    }

    for(int i=2;i<=tot;i++){add(fa[i],i);}
    dfs(1);
    for(int i=2;i<=tot;i++)
    {
        ans=ans+(((siz[i])*(siz[i]+1))/2)*(len[i]-len[fa[i]]);
    }

    cout<<ans<<endl;
    return 0;
}


#include<cstdio>
#include<cstring>
const int N=220000;

char a[N];
int ans,num,n,rank[N],count[N],h[N],rank1[N],sa[N],st[256],tmp[N],k;
int main(){
//	freopen("string.in","r",stdin);
//	freopen("string.out","w",stdout);

	a[0]=2;
	scanf("%s",a+1);
	n=strlen(a)-1;

	memset(st,0,sizeof(st));
	memset(rank,0,sizeof(rank));
	memset(rank1,0,sizeof(rank1));
	for(int i=1; i<=n; i++) st[a[i]]=1;
	for(int i=1; i<=255; i++) st[i]+=st[i-1];
	for(int i=1; i<=n; i++) rank[i]=st[a[i]];

	k=0;
	for(int p=1; k!=n; p=p*2){
		memset(count,0,sizeof(count));
		for(int i=1; i<=n; i++) count[rank[i+p]]++;
		for(int i=1; i<=n; i++) count[i]+=count[i-1];
		for(int i=n; i>=1; i--) tmp[count[rank[i+p]]--]=i;

		memset(count,0,sizeof(count));
		for(int i=1; i<=n; i++) count[rank[i]]++;
		for(int i=1; i<=n; i++) count[i]+=count[i-1];
		for(int i=n; i>=1; i--) sa[count[rank[tmp[i]]]--]=tmp[i];

		memcpy(rank1,rank,sizeof(rank));
		rank[sa[1]]=1;
		k=1;
		for(int i=2; i<=n; i++){
			if(rank1[sa[i]]==rank1[sa[i-1]] and rank1[sa[i]+p]==rank1[sa[i-1]+p]) k--;
			rank[sa[i]]=++k;
		}
	}
//	for (int i=1; i<=n; i++) printf("%d ",sa[i]); printf("\n");
//	for (int i=1; i<=n; i++) printf("%d ",rank[i]); printf("\n");

	k=0;
	for(int i=1; i<=n; i++){
		if(rank[i]==n){
			h[rank[i]]=0;
			continue;
		}
		if(k>0) k--;

		while(k<=n and a[i+k]==a[sa[rank[i]+1]+k]) k++;
		h[rank[i]]=k;
	}

//	for(int i=1; i<=n; i++) printf("%d ",h[i]); printf("\n");

	ans=0;
	h[0]=0;
	for(int i=1; i<=n; i++){
//		printf("%d %d\n",h[i-1]+1,n-sa[i]+1);

		for(int j=h[i-1]+1; j<=n-sa[i]+1; j++){
			int nn=i;
			num=1;

			while(h[nn]>=j){nn++; num++;}

			ans+=(num+1)*num/2;
		}
	}

	printf("%d\n",ans);

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define M 2000005
#define re register
int l,mx[M],fa[M],trie[M][26],cnt=1,last=1;
long long cal[M],a[M],b[M];
char s[M];
inline void fput(long long x){//快速输出int型(无换行符)
    if(x<0)putchar('-'),x=-x;
    if(x>=10)fput(x/10);
    putchar(x%10+'0');
}
inline void input(int c){
	re int p=last,np;np=last=++cnt;
	mx[np]=mx[p]+1;
	while(p&&!trie[p][c])trie[p][c]=np,p=fa[p];
	if(!p)fa[np]=1;
	else{
		re int q=trie[p][c];
		if(mx[q]==mx[p]+1){
			fa[np]=q;
		}else{
			re int nq=++cnt;
			mx[nq]=mx[p]+1;
			//memcpy(trie[nq],trie[q],sizeof(trie[q]));
			for(re int i=0;i<26;i++)trie[nq][i]=trie[q][i];
			fa[nq]=fa[q];
			fa[np]=fa[q]=nq;
			while(trie[p][c]==q)trie[p][c]=nq,p=fa[p];
		}
	}
	last=np;
	cal[np]=1;
	return ;
}
int main(){
	gets(s+1);
	l=strlen(s+1);
	for(re int i=1;i<=l;i++)input(s[i]-'a');
	for(re int i=1;i<=cnt;i++)a[mx[i]]++;
	for(re int i=1;i<=cnt;i++)a[i]+=a[i-1];
	for(re int i=1;i<=cnt;i++)b[a[mx[i]]--]=i;
	re long long ans=0;
	for(re int i=cnt;i>=1;i--){
		long long x=b[i];
		ans+=(cal[x]+1)*cal[x]*(mx[x]-mx[fa[x]])/2;
		cal[fa[x]]+=cal[x];
	}
	fput(ans);
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=200005;
char s[N];
long long ans=0;
struct SAM{
	int len[N],size[N],ch[N][26],fa[N],cnt,last;

	int Head[N],Next[N],Adj[N],tot;

	inline void init(){cnt=last=1;tot=0;}

	inline void insert(int c){
		int np=++cnt,p=last;len[np]=len[p]+1,last=np;
		for (;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
		if (!p) fa[np]=1;
		else {
			int q=ch[p][c];
			if (len[p]+1==len[q]) fa[np]=q;
			else {
				int nq=++cnt;len[nq]=len[p]+1;
				memcpy(ch[nq],ch[q],sizeof(ch[q]));
				fa[nq]=fa[q],fa[q]=fa[np]=nq;
				for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
			}
		}size[np]=1;
	}

	inline void addedge(int u,int v){
		Next[++tot]=Head[u];
		Head[u]=tot;
		Adj[tot]=v;
	}

	inline void build(){
		for (int i=2;i<=cnt;i++) addedge(fa[i],i);
	}

	inline void dfs(int x){
		for (int e=Head[x];e;e=Next[e])
			dfs(Adj[e]),size[x]+=size[Adj[e]];
		ans+=1ll*(len[x]-len[fa[x]])*size[x]*(size[x]+1)>>1ll;
	}
}T;
int main (){
	scanf ("%s",s+1);
	T.init();int n=strlen(s+1);
	for (int i=1;i<=n;i++) T.insert(s[i]-'a');
	T.build();
	T.dfs(1);
	printf ("%lld",ans);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int dp[2005][2005],k;
string str1,str2;
int main()
{
	cin>>str1;
	cin>>str2;
	cin>>k;
	for(int i=1;i<=str1.length();i++)dp[i][0]=k*i;
	for(int i=1;i<=str2.length();i++)dp[0][i]=k*i;
	for(int i=1;i<=str1.length();i++)
		for(int j=1;j<=str2.length();j++)
		{
			dp[i][j] = min(dp[i-1][j-1] + abs(str1[i-1] - str2[j-1]),min(dp[i-1][j],dp[i][j-1]) + k);
		}
	cout<<dp[str1.length()][str2.length()];
	return 0;
}


#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
//#pragma GCC optimize("Ofast,no-stack-protector")
#define int long long
//#define ull signed long long
#define mm 1000007
//#define N 500008
//#define M 2000007
#define oo 1000000000000
//#define ll long long
//ios::sync_with_stdio(false);
#define mod 998244353

using namespace std;
const double eps=1e-7;

int head[mm];
//struct edge
//{
//    int to;int next;
//}e[mm];
struct edge
{
    int to;int next;
}e[mm<<1];
int inde=0;
void add(int u,int v)
{
    e[++inde].to=v;
    e[inde].next=head[u];
    head[u]=inde;
}
///////////////////////////////
char s[mm];
int ans=0;
int len[mm];int ch[mm][26];int siz[mm];
int now=1;int fa[mm];
int tot=1;
void in(int c)
{
    int p=now;
    int id=now=++tot;
    siz[tot]=1;
    len[id]=len[p]+1;
    for(;p&&!ch[p][c];p=fa[p]){ch[p][c]=id;}
    if(!p){fa[id]=1;}
    else{
        int q=ch[p][c];
        if(len[q]==len[p]+1){fa[id]=q;}
        else{
            int idi=++tot;
            fa[idi]=fa[q];len[idi]=len[p]+1;
            for(int i=0;i<26;i++){ch[idi][i]=ch[q][i];}
            fa[q]=fa[id]=idi;
            for(;p&&ch[p][c]==q;p=fa[p]){ch[p][c]=idi;}
        }
    }
}

void dfs(int x)
{
    for(int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        dfs(v);
        siz[x]+=siz[v];
    }
}

signed main()
{
    scanf("%s",s+1);
    for(int i=1;i<=strlen(s+1);i++)
    {
        int tmp=s[i]-'a';
        in(tmp);
    }

    for(int i=2;i<=tot;i++){add(fa[i],i);}
    dfs(1);
    for(int i=2;i<=tot;i++)
    {
        ans=ans+(((siz[i])*(siz[i]+1))/2)*(len[i]-len[fa[i]]);
    }

    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int maxn = 200106;
const int maxc = 27;
char s1[maxn];
int tp;
typedef long long ll;
struct SAM{

	int tot=1,last=1;//last -> 旧主串的节点
	int fa[maxn],len[maxn],size[maxn];
	int cup[maxn],mp[maxn];
	int son[maxn][maxc];
	bool sbd[maxn];
	int val[maxn];

	//建SAM
	void extend (int c){
	    int p=last,np=++tot;
	    last=tot,len[np]=len[p]+1;
	    while (p&&!son[p][c])   son[p][c]=np,p=fa[p];

	    if (!p) fa[np]=1,val[np] = tp;
	    else{

	        int q=son[p][c];
	        if (len[q]==len[p]+1) fa[np]=q;//val[np]=tp;
	        else{

	            int nq=++tot;
	            len[nq]=len[p]+1;
	            fa[nq]=fa[q];
	            fa[np]=fa[q]=nq;
	            memcpy(son[nq],son[q],sizeof(son[q]));
	            while (son[p][c]==q)
					son[p][c]=nq,p=fa[p];
				//val[np] = tp;
	        }
	    }
	    size[np]=1;//该节点right大小初值赋值为1
	}

	void dfs(int k)
	{
		size[k] = 1;
		for (int i = 0 ; i < 26 ; ++i)
		{
			int p = son[k][i];
			if(p)
			{
				if(!size[p])
					dfs(p);
				size[k] += size[p];
			}
		}
	}

	void getSize(){
		for (int i = 1 ; i <=tot;++i) cup[len[i]] = 0;
		for (int i=1;i<=tot;++i)    ++cup[len[i]];
		for (int i=1;i<=tot;++i)    cup[i]+=cup[i-1];
		for (int i=1;i<=tot;++i)    mp[cup[len[i]]--]=i;

		for (int i=tot;i>=1;--i)
		{
			int p = mp[i];
		  	 size[fa[p]]+=size[p];
		}
	}

    inline void init()
    {
        last = tot = 1;
        fa[1]=0;
        memset(son,0,sizeof(son));

    }

    void solve(){
    	ll res = 0;
 		for (int i = 1 ; i <= tot ; ++i){
 			ll cnt = len[i] - len[fa[i]];
 			ll k = size[i];
 			res = (k+1) * k /2 * cnt +res;
		}
		printf("%lld\n",res);
	}
}sam;

signed main(){
	sam.init();
	cin >> s1;
	int slen = strlen(s1);
	for (int i = 0  ; i < slen ; ++i){
		int c = s1[i] - 'a';
		sam.extend(c);
	}
	sam.getSize();
	sam.solve();
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define M 2000005
#define re register
int l,mx[M],fa[M],trie[M][26],cnt=1,last=1,cal[M];
char s[M];
inline void fput(long long x){//快速输出int型(无换行符)
    if(x>=10)fput(x/10);
    putchar(x%10+'0');
}
inline void input(int c){
	re int p=last,np;np=last=++cnt;
	mx[np]=mx[p]+1;
	while(p&&!trie[p][c])trie[p][c]=np,p=fa[p];
	if(!p)fa[np]=1;
	else{
		int q=trie[p][c];
		if(mx[q]==mx[p]+1){
			fa[np]=q;
		}else{
			int nq=++cnt;
			mx[nq]=mx[p]+1;
			memcpy(trie[nq],trie[q],sizeof(trie[q]));
			fa[nq]=fa[q];
			fa[np]=fa[q]=nq;
			while(trie[p][c]==q)trie[p][c]=nq,p=fa[p];
		}
	}
	last=np;
	return ;
}
inline void cmp(){
	re int p=1;
	for(re int i=1;i<=l;i++){
		int q=s[i]-'a';
		p=trie[p][q];
		int pp=p;
		while(pp!=1){
			cal[pp]++;
			pp=fa[pp];
		}
	}
	return ;
}
inline long long cp(long long x){
	return (x+1)*x/2;
}
int main(){
	gets(s+1);
	l=strlen(s+1);
	for(re int i=1;i<=l;i++)input(s[i]-'a');
	cmp();
	re long long ans=0;
	for(re long long i=1;i<=cnt;i++){
		//printf("%d %d %d\n",i,cal[i],mx[i]);
		ans+=cp(cal[i])*(mx[i]-mx[fa[i]]);
		//ans=max(ans,(long long)cal[i]*mx[i]*(cal[i]!=1));
	}
	fput(ans);
	return 0;
}


#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
//#pragma GCC optimize("Ofast,no-stack-protector")
#define int long long
//#define ull signed long long
#define mm 200007
//#define N 500008
//#define M 2000007
#define oo 1000000000000
//#define ll long long
//ios::sync_with_stdio(false);
#define mod 998244353

using namespace std;
const double eps=1e-7;

int head[mm];
//struct edge
//{
//    int to;int next;
//}e[mm];
struct edge
{
    int to;int next;
}e[mm<<1];
int inde=0;
void add(int u,int v)
{
    e[++inde].to=v;
    e[inde].next=head[u];
    head[u]=inde;
}
///////////////////////////////
char s[mm];
int ans=0;
int len[mm];int ch[mm][26];int siz[mm];
int now=1;int fa[mm];
int tot=1;
void in(int c)
{
    int p=now;
    int id=now=++tot;
    siz[tot]=1;
    len[id]=len[p]+1;
    for(;p&&!ch[p][c];p=fa[p]){ch[p][c]=id;}
    if(!p){fa[id]=1;}
    else{
        int q=ch[p][c];
        if(len[q]==len[p]+1){fa[id]=q;}
        else{
            int idi=++tot;
            fa[idi]=fa[q];len[idi]=len[p]+1;
            for(int i=0;i<26;i++){ch[idi][i]=ch[q][i];}
            fa[q]=fa[id]=idi;
            for(;p&&ch[p][c]==q;p=fa[p]){ch[p][c]=idi;}
        }
    }
}

void dfs(int x)
{
    for(int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        dfs(v);
        siz[x]+=siz[v];
    }
}

signed main()
{
    scanf("%s",s+1);
    for(int i=1;i<=strlen(s+1);i++)
    {
        int tmp=s[i]-'a';
        in(tmp);
    }
//    for(int i=tot;i>1;i--)
//    {
//        siz[fa[i]]+=siz[i];
//    }

    for(int i=2;i<=tot;i++){add(fa[i],i);}
    dfs(1);
    for(int i=2;i<=tot;i++)
    {
        ans += 1ll * siz[i] * (siz[i] + 1) / 2 * (len[i] - len[fa[i]]);
    }

    cout<<ans<<endl;
    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=100;

/*
 *suffix array
 *倍增算法  O(n*logn)
 *待排序数组长度为n,放在0~n-1中，在最后面补一个0
 *build_sa( ,n+1,m+1); //注意是n+1,m是s数组中的最大值;
 *getHeight(,n);
 *例如：

 *n   = 8;
 *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0，其他大于0
 *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值，rank[n]必定为0无效值
 *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值，sa[0]必定为n是无效值
 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
 *
 */

int sa[maxn];//SA数组，表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[maxn],t2[maxn],c[maxn];//求SA数组需要的中间变量，不需要赋值
int rk[maxn],height[maxn];
//待排序的字符串放在s数组中，从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0，r[n-1]=0
//函数结束以后结果放在sa数组中
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x=t1,*y=t2;
    //第一轮基数排序，如果s的最大值很大，可改为快速排序
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        //直接利用sa数组排序第二关键字
        for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        //根据sa和x数组计算新的x数组
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n)break;
        m=p;//下次基数排序的最大值
    }
}
void getHeight(int s[],int n)
{
    int i,j,k=0;
    for(i=0;i<=n;i++) rk[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[rk[i]]=k;
    }
}
ll cnt(int x)
{
    return 1ll*x*(x+1)/2;
}

char s[maxn];
int a[maxn];
int st[maxn];
vector<pair<pair<int, int>, int>> v;//单调栈
int main()
{
    scanf("%s",s);
    int l=(int)strlen(s);
    rep(i,0,l) a[i]=s[i]-'a'+1;
    a[l]=0;
    build_sa(a,l+1,60);
    getHeight(a,l);
    ll ans=0;
    height[l+1]=0;
    sa[l+1]=l;
    rep(i,1,l+2)
    {
        while (!v.empty() && v.back().first.second > height[i])
        {
            auto &end = v.back();// 某子串出现i-end.second次
            if (end.first.first < height[i])//队尾公共前缀长度小于当前公共前缀长度
            {// 有（end.公共前缀长度减去当前公共前缀长度）种子串
                ans += (end.first.second -height[i]) * cnt(i - end.second);
                end.first.second = height[i];//维护非严格单调增栈
            }
            else
            {
                ans += (end.first.second - end.first.first) * cnt(i - end.second);
                v.pop_back();//维护非严格单调增栈
            }
        }
        v.push_back({{height[i], l - sa[i]}, i});
    }
    printf("%lld\n",ans);

    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=100;
/*
 *suffix array
 *倍增算法  O(n*logn)
 *待排序数组长度为n,放在0~n-1中，在最后面补一个0
 *build_sa( ,n+1,m+1); //注意是n+1,m是s数组中的最大值;
 *getHeight(,n);
 *例如：

 *n   = 8;
 *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0，其他大于0
 *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值，rank[n]必定为0无效值
 *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值，sa[0]必定为n是无效值
 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
 *
 */

int sa[maxn];//SA数组，表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[maxn],t2[maxn],c[maxn];//求SA数组需要的中间变量，不需要赋值
int rk[maxn],height[maxn];
//待排序的字符串放在s数组中，从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0，r[n-1]=0
//函数结束以后结果放在sa数组中
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x=t1,*y=t2;
    //第一轮基数排序，如果s的最大值很大，可改为快速排序
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        //直接利用sa数组排序第二关键字
        for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        //根据sa和x数组计算新的x数组
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n)break;
        m=p;//下次基数排序的最大值
    }
}
void getHeight(int s[],int n)
{
    int i,j,k=0;
    for(i=0;i<=n;i++) rk[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[rk[i]]=k;
    }
}

char s[maxn];
int a[maxn];
int st[maxn],pre[maxn];
ll ans[maxn];
int main()
{
    scanf("%s",s);
    int l=(int)strlen(s);
    rep(i,0,l) a[i]=s[i]-'a'+1;
    a[l]=0;
    build_sa(a,l+1,60);
    getHeight(a,l);
    ll res=1ll*l*(l+1)/2;
    int top=0;
    ans[1]=0;st[0]=1;
    rep(i,2,l+1)
    {
        if(!height[i])
        {
            st[top]=i,ans[i]=0;
            continue;
        }
        while(top&&height[st[top]]>=height[i]) top--;
        ans[i]=ans[st[top]]+1ll*(i-st[top])*height[i];
        st[++top]=i;
        res+=ans[i];
    }
    printf("%lld\n",res);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=1e5+100;

/*
 *suffix array
 *倍增算法  O(n*logn)
 *待排序数组长度为n,放在0~n-1中，在最后面补一个0
 *build_sa( ,n+1,m+1); //注意是n+1,m是s数组中的最大值;
 *getHeight(,n);
 *例如：

 *n   = 8;
 *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0，其他大于0
 *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值，rank[n]必定为0无效值
 *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值，sa[0]必定为n是无效值
 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
 *
 */

int sa[maxn];//SA数组，表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[maxn],t2[maxn],c[maxn];//求SA数组需要的中间变量，不需要赋值
int rk[maxn],height[maxn];
//待排序的字符串放在s数组中，从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0，r[n-1]=0
//函数结束以后结果放在sa数组中
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x=t1,*y=t2;
    //第一轮基数排序，如果s的最大值很大，可改为快速排序
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        //直接利用sa数组排序第二关键字
        for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        //根据sa和x数组计算新的x数组
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n)break;
        m=p;//下次基数排序的最大值
    }
}
void getHeight(int s[],int n)
{
    int i,j,k=0;
    for(i=0;i<=n;i++) rk[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[rk[i]]=k;
    }
}
ll cnt(int x)
{
    return 1ll*x*(x+1)/2;
}

char s[maxn];
int a[maxn];
int st[maxn];
vector<pair<pair<int, int>, int>> v;//单调栈
int main()
{
    scanf("%s",s);
    int l=(int)strlen(s);
    rep(i,0,l) a[i]=s[i]-'a'+1;
    a[l]=0;
    build_sa(a,l+1,60);
    getHeight(a,l);
    ll ans=0;
    height[l+1]=0;
    sa[l+1]=l;
    rep(i,1,l+2)
    {
        while (!v.empty() && v.back().first.second > height[i])
        {
            auto &end = v.back();// 某子串出现i-end.second次
            if (end.first.first < height[i])//队尾公共前缀长度小于当前公共前缀长度
            {// 有（end.公共前缀长度减去当前公共前缀长度）种子串
                ans += (end.first.second -height[i]) * cnt(i - end.second);
                end.first.second = height[i];//维护非严格单调增栈
            }
            else
            {
                ans += (end.first.second - end.first.first) * cnt(i - end.second);
                v.pop_back();//维护非严格单调增栈
            }
        }
        v.push_back({{height[i], l - sa[i]}, i});
    }
    printf("%lld\n",ans);

    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=100;
/*
 *suffix array
 *倍增算法  O(n*logn)
 *待排序数组长度为n,放在0~n-1中，在最后面补一个0
 *build_sa( ,n+1,m+1); //注意是n+1,m是s数组中的最大值;
 *getHeight(,n);
 *例如：

 *n   = 8;
 *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0，其他大于0
 *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值，rank[n]必定为0无效值
 *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值，sa[0]必定为n是无效值
 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
 *
 */

int sa[maxn];//SA数组，表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[maxn],t2[maxn],c[maxn];//求SA数组需要的中间变量，不需要赋值
int rk[maxn],height[maxn];
//待排序的字符串放在s数组中，从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0，r[n-1]=0
//函数结束以后结果放在sa数组中
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x=t1,*y=t2;
    //第一轮基数排序，如果s的最大值很大，可改为快速排序
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        //直接利用sa数组排序第二关键字
        for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        //根据sa和x数组计算新的x数组
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n)break;
        m=p;//下次基数排序的最大值
    }
}
void getHeight(int s[],int n)
{
    int i,j,k=0;
    for(i=0;i<=n;i++) rk[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[rk[i]]=k;
    }
}

char s[maxn];
int a[maxn];
int st[maxn],ans[maxn],pre[maxn];
int main()
{
    scanf("%s",s);
    int l=(int)strlen(s);
    rep(i,0,l) a[i]=s[i]-'a'+1;
    a[l]=0;
    build_sa(a,l+1,60);
    getHeight(a,l);
    ll res=1ll*l*(l+1)/2;
    int top=0;
    rep(i,2,l+1)
    {
        while(top&&height[st[top]]>height[i])
        {
            top--;
        }
        if(!top) st[top]=i-1,ans[i-1]=0;
        ans[i]=ans[st[top]]+(i-st[top])*height[i];
        st[++top]=i;
        res+=ans[i];
    }

    printf("%lld\n",res);
    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=1e5+100;

/*
 *suffix array
 *倍增算法  O(n*logn)
 *待排序数组长度为n,放在0~n-1中，在最后面补一个0
 *build_sa( ,n+1,m+1); //注意是n+1,m是s数组中的最大值;
 *getHeight(,n);
 *例如：

 *n   = 8;
 *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0，其他大于0
 *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值，rank[n]必定为0无效值
 *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值，sa[0]必定为n是无效值
 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
 *
 */

int sa[maxn];//SA数组，表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[maxn],t2[maxn],c[maxn];//求SA数组需要的中间变量，不需要赋值
int rk[maxn],height[maxn];
//待排序的字符串放在s数组中，从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0，r[n-1]=0
//函数结束以后结果放在sa数组中
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x=t1,*y=t2;
    //第一轮基数排序，如果s的最大值很大，可改为快速排序
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        //直接利用sa数组排序第二关键字
        for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        //根据sa和x数组计算新的x数组
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n)break;
        m=p;//下次基数排序的最大值
    }
}
void getHeight(int s[],int n)
{
    int i,j,k=0;
    for(i=0;i<=n;i++) rk[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[rk[i]]=k;
    }
}
ll cnt(int x)
{
    return 1ll*x*x;
}

char s[maxn];
int a[maxn];
int st[maxn];
vector<pair<pair<int, int>, int>> v;//单调栈
int main()
{
    scanf("%s",s);
    int l=(int)strlen(s);
    rep(i,0,l) a[i]=s[i]-'a'+1;
    a[l]=0;
    build_sa(a,l+1,60);
    getHeight(a,l);
    ll ans=0;
    height[l+1]=0;
    sa[l+1]=l;
    rep(i,1,l+2)
    {
        while(!v.empty()&&v.back().first.second>height[i])
        {
            auto &end=v.back();// 某子串出现i-end.second次
            if (end.first.first<height[i])//队尾公共前缀长度小于当前公共前缀长度
            {// 有（end.公共前缀长度减去当前公共前缀长度）种子串
                ans+=(end.first.second-height[i])*cnt(i-end.second);
                end.first.second=height[i];//维护非严格单调增栈
            }
            else
            {
                ans+=(end.first.second-end.first.first)*cnt(i-end.second);
                v.pop_back();//维护非严格单调增栈
            }
        }
        v.push_back({{height[i],l-sa[i]},i});
    }
    ans+=1ll*l*(l+1)/2;
    printf("%lld\n",ans/2);

    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define fi first
#define se second
#define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
const int inf=0x3fffffff;
const ll mod=1000000007;
const int maxn=1e5+100;
/*
 *suffix array
 *倍增算法  O(n*logn)
 *待排序数组长度为n,放在0~n-1中，在最后面补一个0
 *build_sa( ,n+1,m+1); //注意是n+1,m是s数组中的最大值;
 *getHeight(,n);
 *例如：

 *n   = 8;
 *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0，其他大于0
 *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值，rank[n]必定为0无效值
 *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值，sa[0]必定为n是无效值
 *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
 *
 */

int sa[maxn];//SA数组，表示将S的n个后缀从小到大排序后把排好序的
//的后缀的开头位置顺次放入SA中
int t1[maxn],t2[maxn],c[maxn];//求SA数组需要的中间变量，不需要赋值
int rk[maxn],height[maxn];
//待排序的字符串放在s数组中，从s[0]到s[n-1],长度为n,且最大值小于m,
//除s[n-1]外的所有s[i]都大于0，r[n-1]=0
//函数结束以后结果放在sa数组中
void build_sa(int s[],int n,int m)
{
    int i,j,p,*x=t1,*y=t2;
    //第一轮基数排序，如果s的最大值很大，可改为快速排序
    for(i=0;i<m;i++)c[i]=0;
    for(i=0;i<n;i++)c[x[i]=s[i]]++;
    for(i=1;i<m;i++)c[i]+=c[i-1];
    for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i;
    for(j=1;j<=n;j<<=1)
    {
        p=0;
        //直接利用sa数组排序第二关键字
        for(i=n-j;i<n;i++)y[p++]=i;//后面的j个数第二关键字为空的最小
        for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
        //这样数组y保存的就是按照第二关键字排序的结果
        //基数排序第一关键字
        for(i=0;i<m;i++)c[i]=0;
        for(i=0;i<n;i++)c[x[y[i]]]++;
        for(i=1;i<m;i++)c[i]+=c[i-1];
        for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
        //根据sa和x数组计算新的x数组
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(i=1;i<n;i++)
            x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
        if(p>=n)break;
        m=p;//下次基数排序的最大值
    }
}
void getHeight(int s[],int n)
{
    int i,j,k=0;
    for(i=0;i<=n;i++) rk[sa[i]]=i;
    for(i=0;i<n;i++)
    {
        if(k)k--;
        j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
        height[rk[i]]=k;
    }
}

char s[maxn];
int a[maxn];
int st[maxn],pre[maxn];
ll ans[maxn];
int main()
{
    scanf("%s",s);
    int l=(int)strlen(s);
    rep(i,0,l) a[i]=s[i]-'a'+1;
    a[l]=0;
    build_sa(a,l+1,60);
    getHeight(a,l);
    ll res=1ll*l*(l+1)/2;
    int top=0;
    ans[1]=0;st[0]=1;
    rep(i,2,l+1)
    {
        if(!height[i])
        {
            st[top]=i,ans[i]=0;
            continue;
        }
        while(top&&height[st[top]]>=height[i]) top--;
        ans[i]=ans[st[top]]+1ll*(i-st[top])*height[i];
        st[++top]=i;
        res+=ans[i];
    }
    printf("%lld\n",res);
    return 0;
}


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

#define N 100010

int s[N], m, n, lcp[N], sa[N], wa[N], x[N], y[N], wv[N];
long long ans;

inline int cmp(int *r, int a, int b, int l) {return r[a] == r[b] && r[a + l] == r[b + l];}

void buildsa() {
	for (int i = 0; i <= m; i ++) wa[i] = 0;
	x[n] = y[n] = s[n] = 0;
	for(int i = 0; i < n; i ++) wa[x[i] = s[i]] ++; ///s[i] >= 1
	for(int i = 1; i <= m; i ++) wa[i] += wa[i - 1];
	for(int i = n - 1; i >= 0; i --) sa[-- wa[x[i]]] = i;
	for (int j = 1,p = 1; p < n; j *= 2, m = p) {
		p = 0;
		for (int i = n - j; i < n; i ++) y[p ++] = i;
		for (int i = 0; i < n; i ++) if (sa[i] >= j) y[p ++] = sa[i] - j;
		for (int i = 0; i < n; i ++) wv[i] = x[y[i]];
		for (int i = 0; i <= m; i ++) wa[i] = 0;
		for (int i = 0; i < n; i ++) wa[wv[i]] ++;
		for (int i = 1; i <= m; i ++) wa[i] += wa[i - 1];
		for (int i = n - 1; i >= 0; i --) sa[-- wa[wv[i]]] = y[i];
		swap(x, y), p = 1, x[sa[0]] = 1;
		for (int i = 1; i < n; i ++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p: ++ p;
	}
	return;
}

void calclcp() {
	lcp[0] = 0;
	for (int i = 0; i < n; i ++) x[sa[i]] = i;
	for (int h = 0, i = 0; i < n; i ++) if (x[i] > 0) {
		int j = sa[x[i] - 1];
		while (s[i + h] == s[j + h]) ++ h;
		lcp[x[i]] = h;
		if (h > 0) h --;
	}
}

int righ[N], lef[N];
char t[N];
map <pair <int, int>, int> vis;

int main() {
	scanf("%s", t);
	n = strlen(t); m = 300;
	for (int i = 0; i < n; i ++) s[i] = t[i] - 'a' + 1;
	buildsa(); calclcp();
	lef[1] = 1;
	for (int i = 2; i < n; i ++) {
		int k = i;
		while (k > 1 && lcp[k - 1] >= lcp[i]) k = lef[k - 1];
		lef[i] = k;
	}
	righ[n - 1] = n - 1;
	for (int i = n - 2; i >= 1; i --) {
		int k = i;
		while (k < n - 1 && lcp[k + 1] >= lcp[i]) k = righ[k + 1];
		righ[i] = k;
	}
	lcp[n] = 0;
	for (int i = 0; i < n; i ++) ans += (n - sa[i] - max(lcp[i], lcp[i + 1]));
	for (int i = 1; i < n; i ++) {
		if (vis[{lef[i], righ[i]}]) continue;
		else {
			vis[{lef[i], righ[i]}] = 1;
			ans += 1ll * (lcp[i] - max(lcp[lef[i] - 1], lcp[righ[i] + 1])) * (righ[i] - lef[i] + 3) * (righ[i] - lef[i] + 2) / 2;
		}
	}
	printf("%I64d\n", ans);
}


#include <bits/stdc++.h>
using namespace std;
#define N 100200
int t, num, n, m, last;
int nxt[N<<1][26], link[N<<1], dp[N<<1], cnt[N<<1], ord[N<<1];
int occur[N<<1];
char s[N];

void init() {
    m = 0;
    last = ++ m;
    memset(nxt[last], 0, sizeof nxt[last]);
    occur[last] = 0;
    dp[last] = 0;
}

void extend(int c) {
    if (nxt[last][c] && dp[nxt[last][c]] == dp[last] + 1) {
        last = nxt[last][c];
        occur[last] ++;
        return;
    }
    int x = last, y = last = ++ m;
    memset(nxt[y], 0, sizeof nxt[y]);
    occur[y] = 1;
    dp[y] = dp[x] + 1;
    while (x && !nxt[x][c]) nxt[x][c] = y, x = link[x];
    if (!x) link[y] = 1;
    else {
        int z = nxt[x][c];
        if (dp[z] == dp[x] + 1) link[y] = z;
        else {
            int u = ++ m;
            memcpy(nxt[u], nxt[z], sizeof nxt[u]);
            link[u] = link[z], link[z] = link[y] = u;
            occur[u] = 0;
            dp[u] = dp[x] + 1;
            while (x && nxt[x][c] == z) nxt[x][c] = u, x = link[x];
        }
    }
}

typedef long long ll;

int main() {
	scanf("%s", s);
	n = strlen(s);
	init();
	for (int i = 0; i < n; i ++) extend(s[i] - 'a');
	for (int i = 1; i <= m; i ++) cnt[i] = 0;
	for (int i = 1; i <= m; i ++) cnt[dp[i]] ++;
	for (int i = 1; i <= m; i ++) cnt[i] += cnt[i-1];
	for (int i = 1; i <= m; i ++) ord[cnt[dp[i]]--] = i;
	for (int i = m; i >= 1; i --) occur[link[ord[i]]] += occur[ord[i]];
	ll ans = 0;
	for (int i = 1; i <= m; i ++) ans += 1ll * (dp[i] - dp[link[i]]) * (occur[i] + 1) * occur[i] / 2;
	printf("%I64d\n", ans);
}


/** I can do this all day **/

#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;

typedef long long                   ll;
typedef long double                 ld;
typedef pair<int,int>               pii;
typedef pair<ll,ll>                 pll;
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second
#define Mp                          make_pair
#define fast_io                     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_io                     freopen("in.txt" , "r+" , stdin) ; freopen("out.txt" , "w+" , stdout);
#define endl                        "\n"

const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
const ll mod2 = 998244353;
const ll inf = 8e18;
const int LOG = 20;

string s;

int n, rnk[LOG][N], A[N], T, v[N], L[N], R[N];

bool cmp(int i, int j)
{
    if(T && rnk[T - 1][i] == rnk[T - 1][j])
    {
	if(max(i, j) + (1 << (T - 1)) > n) return i > j;
	return rnk[T - 1][i + (1 << (T - 1))] < rnk[T - 1][j + (1 << (T - 1))];
    }
    return rnk[T - 1][i] < rnk[T - 1][j];
}

void B()
{
    for(int i = 1; i <= n; i ++)
    {
	A[i] = i;
	rnk[0][i] = s[i] - 'a' + 1;
    }
    for(T = 1; T < LOG; T ++)
    {
	sort(A + 1, A + n + 1, cmp);
	rnk[T][A[1]] = 1;
	for(int i = 2; i <= n; i ++)
	{
	    rnk[T][A[i]] = rnk[T][A[i - 1]] + cmp(A[i - 1], A[i]);
	}
    }
}

int lcp(int i, int j)
{
    int res = 0;
    for(T = LOG - 1; ~T; T --)
    {
	if(max(i, j) + (1 << T) - 1 <= n && rnk[T][i] == rnk[T][j])
	{
	    i += 1 << T;
	    j += 1 << T;
	    res |= 1 << T;
	}
    }
    return res;
}

ll C(ll x)
{
    return (x + 1) * (x) / 2ll;
}

int main()
{
    fast_io;
    cin >> s;
    n = (int)s.size();
    s = "." + s;
    B();
    for(int i = 2; i <= n; i ++)
    {
	v[i] = lcp(A[i - 1], A[i]);
	/// cout << v[i] << " ";
    }
    /// cout << endl;
    deque < int > dq;
    v[n + 1] = v[1] = -1e9;
    dq.push_back(1);
    for(int i = 2; i <= n; i ++)
    {
	while(v[dq.back()] >= v[i])
	{
	    dq.pop_back();
	}
	L[i] = dq.back() - 1;
	dq.push_back(i);
    }
    dq.clear();
    dq.push_back(n + 1);
    for(int i = n; i >= 2; i --)
    {
	while(v[dq.back()] > v[i])
	{
	    dq.pop_back();
	}
	R[i] = dq.back() - 1;
	dq.push_back(i);
    }
    ll tot = 0;
    for(ll i = 2; i <= n; i ++)
    {
	/// cout << v[i] << " " << L[i] << " " << R[i] << endl;
	tot += 1ll * (i - L[i] - 1) * (R[i] - i + 1) * v[i];
    }
    tot += C(n);
    cout << tot << endl;
    return 0;
}
/*!
        stay away from negative people they have a problem for every solution !
*/


/** I can do this all day **/

#pragma GCC optimize("O2")
#include <bits/stdc++.h>
using namespace std;

typedef long long                   ll;
typedef long double                 ld;
typedef pair<int,int>               pii;
typedef pair<ll,ll>                 pll;
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second
#define Mp                          make_pair
#define fast_io                     ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define file_io                     freopen("in.txt" , "r+" , stdin) ; freopen("out.txt" , "w+" , stdout);
#define endl                        "\n"

const int N = 1e6 + 10;
const ll mod = 1e9 + 7;
const ll mod2 = 998244353;
const ll inf = 8e18;
const int LOG = 20;

string s;

int n, rnk[LOG][N], A[N], T, v[N], L[N], R[N];

bool cmp(int i, int j)
{
    if(T && rnk[T - 1][i] == rnk[T - 1][j])
    {
	if(max(i, j) + (1 << (T - 1)) > n) return i > j;
	return rnk[T - 1][i + (1 << (T - 1))] < rnk[T - 1][j + (1 << (T - 1))];
    }
    return rnk[T - 1][i] < rnk[T - 1][j];
}

void B()
{
    for(int i = 1; i <= n; i ++)
    {
	A[i] = i;
	rnk[0][i] = s[i] - 'a' + 1;
    }
    for(T = 1; T < LOG; T ++)
    {
	sort(A + 1, A + n + 1, cmp);
	rnk[T][A[1]] = 1;
	for(int i = 2; i <= n; i ++)
	{
	    rnk[T][A[i]] = rnk[T][A[i - 1]] + cmp(A[i - 1], A[i]);
	}
    }
}

int lcp(int i, int j)
{
    int res = 0;
    for(T = LOG - 1; ~T; T --)
    {
	if(max(i, j) + (1 << T) - 1 <= n && rnk[T][i] == rnk[T][j])
	{
	    i += 1 << T;
	    j += 1 << T;
	    res |= 1 << T;
	}
    }
    return res;
}

ll C(ll x)
{
    return (x + 1) * (x) / 2;
}

int main()
{
    fast_io;
    cin >> s;
    n = (int)s.size();
    s = "." + s;
    B();
    for(int i = 2; i <= n; i ++)
    {
	v[i] = lcp(A[i - 1], A[i]);
	/// cout << v[i] << " ";
    }
    /// cout << endl;
    deque < int > dq;
    v[n + 1] = v[1] = -1e9;
    dq.push_back(1);
    for(int i = 2; i <= n; i ++)
    {
	while(v[dq.back()] >= v[i])
	{
	    dq.pop_back();
	}
	L[i] = dq.back() - 1;
	dq.push_back(i);
    }
    dq.clear();
    dq.push_back(n + 1);
    for(int i = n; i >= 2; i --)
    {
	while(v[dq.back()] > v[i])
	{
	    dq.pop_back();
	}
	R[i] = dq.back() - 1;
	dq.push_back(i);
    }
    ll tot = 0;
    for(int i = 2; i <= n; i ++)
    {
	/// cout << v[i] << " " << L[i] << " " << R[i] << endl;
	tot += (i - L[i] - 1) * (R[i] - i + 1) * v[i];
    }
    tot += C(n);
    cout << tot << endl;
    return 0;
}
/*!
        stay away from negative people they have a problem for every solution !
*/


#include <bits/stdc++.h>

#define ln                '\n'
#define all(dat)           dat.begin(), dat.end()
#define loop(i, to)        for (int i = 0; i < to; ++i)
#define cont(i, to)        for (int i = 1; i <= to; ++i)
#define circ(i, fm, to)    for (int i = fm; i <= to; ++i)
#define foreach(i, dat)    for (__typeof(dat.begin()) i = dat.begin(); i != dat.end(); ++i)

typedef long long          num;

using namespace std;

const int nsz = 1e5, ndsz = 2 * nsz, alphasz = 26;
int es, hd[ndsz + 5];
num cnt[nsz + 5], ans;
string s;

struct suffix_automaton {
	bool sf[ndsz + 5];
	int sz, rt, lst, lnk[ndsz + 5], len[ndsz + 5], g[ndsz + 5][alphasz];

	suffix_automaton() { rt = lst = ++sz; }

	void inline ins(char ch) {
		int c = ch - 'a', p = lst, u = lst = ++sz;
		sf[u] = 1, len[u] = len[p] + 1;
		for (; p && !g[p][c]; g[p][c] = u, p = lnk[p]);
		if (!p) { lnk[u] = rt; return; }
		int q = g[p][c];
		if (len[q] == len[p] + 1)  lnk[u] = q;
		else {
			int v = ++sz;
			len[v] = len[p] + 1, lnk[v] = lnk[q];
			memcpy(g[v], g[q], sizeof(g[q]));
			for (; p && g[p][c] == q; g[p][c] = v, p = lnk[p]);
			lnk[u] = lnk[q] = v;
		}
	}

	void inline ins(string s) {
		loop (i, s.size()) {
			ins(s[i]);
		}
	}
};
suffix_automaton sam;

struct edge {
	int nxt, to;

	edge(int nxt = 0, int to = 0) { this->nxt = nxt, this->to = to; }
};
edge e[ndsz + 5];

void inline link(int u, int v) {
	e[++es] = edge(hd[u], v), hd[u] = es;
}

void dfs(int u) {
	cnt[u] = sam.sf[u];
	for (int i = hd[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		dfs(v);
		cnt[u] += cnt[v];
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin >> s;
	sam.ins(s);
	cont (u, sam.sz) {
		if (!sam.lnk[u])  continue;
		link(sam.lnk[u], u);
	}
	dfs(sam.rt);
	cont (u, sam.sz) {
		if (u == sam.rt)  continue;
		ans += cnt[u] * (cnt[u] + 1) / 2 * (sam.len[u] - sam.len[sam.lnk[u]]);
	}
	cout << ans << ln;
}


#include <bits/stdc++.h>

#define ln                '\n'
#define all(dat)           dat.begin(), dat.end()
#define loop(i, to)        for (int i = 0; i < to; ++i)
#define cont(i, to)        for (int i = 1; i <= to; ++i)
#define circ(i, fm, to)    for (int i = fm; i <= to; ++i)
#define foreach(i, dat)    for (__typeof(dat.begin()) i = dat.begin(); i != dat.end(); ++i)

typedef long long          num;

using namespace std;

const int nsz = 1e5, ndsz = 2 * nsz, alphasz = 26;
int es, hd[ndsz + 5];
num cnt[ndsz + 5], ans;
string s;

struct suffix_automaton {
	bool sf[ndsz + 5];
	int sz, rt, lst, lnk[ndsz + 5], len[ndsz + 5], g[ndsz + 5][alphasz];

	suffix_automaton() { rt = lst = ++sz; }

	void inline ins(char ch) {
		int c = ch - 'a', p = lst, u = lst = ++sz;
		sf[u] = 1, len[u] = len[p] + 1;
		for (; p && !g[p][c]; g[p][c] = u, p = lnk[p]);
		if (!p) { lnk[u] = rt; return; }
		int q = g[p][c];
		if (len[q] == len[p] + 1)  lnk[u] = q;
		else {
			int v = ++sz;
			len[v] = len[p] + 1, lnk[v] = lnk[q];
			memcpy(g[v], g[q], sizeof(g[q]));
			for (; p && g[p][c] == q; g[p][c] = v, p = lnk[p]);
			lnk[u] = lnk[q] = v;
		}
	}

	void inline ins(string s) {
		loop (i, s.size()) {
			ins(s[i]);
		}
	}
};
suffix_automaton sam;

struct edge {
	int nxt, to;

	edge(int nxt = 0, int to = 0) { this->nxt = nxt, this->to = to; }
};
edge e[ndsz + 5];

void inline link(int u, int v) {
	e[++es] = edge(hd[u], v), hd[u] = es;
}

void dfs(int u) {
	cnt[u] = sam.sf[u];
	for (int i = hd[u]; i; i = e[i].nxt) {
		int v = e[i].to;
		dfs(v);
		cnt[u] += cnt[v];
	}
}

int main() {
	ios::sync_with_stdio(0);
	cin >> s;
	sam.ins(s);
	cont (u, sam.sz) {
		if (!sam.lnk[u])  continue;
		link(sam.lnk[u], u);
	}
	dfs(sam.rt);
	cont (u, sam.sz) {
		if (u == sam.rt)  continue;
		ans += cnt[u] * (cnt[u] + 1) / 2 * (sam.len[u] - sam.len[sam.lnk[u]]);
	}
	cout << ans << ln;
}


/*DennyQi 2019*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define ll long long
using namespace std;
const int N = 200010;
const int P = 998244353;
const int INF = 0x3f3f3f3f;
inline int read(){
    int x(0),w(1); char c = getchar();
    while(c^'-' && (c<'0' || c>'9')) c = getchar();
    if(c=='-') w = -1, c = getchar();
    while(c>='0' && c<='9') x = (x<<3)+(x<<1)+c-'0', c = getchar();
    return x*w;
}
char s[N];
int n,las,tot,len[N],son[N][26],fa[N],sz[N],head[N],nxt[N<<1],to[N<<1],cnte;
ll ans;
inline void add(int u, int v){
	to[++cnte] = v;
	nxt[cnte] = head[u];
	head[u] = cnte;
}
inline void insert(char c, int idx){
	int p = las;
	las = ++tot;
	sz[las] = 1;
	len[tot] = idx;
	for(; p && !son[p][c]; p = fa[p]) son[p][c] = las;
	if(!p){ fa[las] = 1; return; }
	int q = son[p][c];
	if(len[q] == len[p]+1){ fa[las] = q; return; }
	len[++tot] = len[p]+1;
	memcpy(son[tot],son[q],sizeof(son[q])), fa[tot] = fa[q];
	fa[q] = tot, fa[las] = tot;
	for(; son[p][c] == q; p = fa[p]) son[p][c] = tot;
}
void dfs(int u){
	for(int i = head[u]; i; i = nxt[i]){
		dfs(to[i]);
		sz[u] += sz[to[i]];
	}
	ans += 1ll*sz[u]*(sz[u]+1)/2*(len[u]-len[fa[u]]);
}
int main(){
	// freopen("file.in","r",stdin);
	scanf("%s",s+1);
	n = strlen(s+1);
	las = tot = 1;
	for(int i = 1; i <= n; ++i){
		insert(s[i]-'a',i);
	}
	for(int i = 2; i <= tot; ++i){
		add(fa[i],i);
	}
	dfs(1);
	printf("%lld\n",ans);
	return 0;
}


/*DennyQi 2019*/
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#define ll long long
using namespace std;
const int N = 200010;
const int P = 998244353;
const int INF = 0x3f3f3f3f;
inline int read(){
    int x(0),w(1); char c = getchar();
    while(c^'-' && (c<'0' || c>'9')) c = getchar();
    if(c=='-') w = -1, c = getchar();
    while(c>='0' && c<='9') x = (x<<3)+(x<<1)+c-'0', c = getchar();
    return x*w;
}
char s[N];
int n,las,tot,len[N],son[N][26],fa[N],sz[N],head[N],nxt[N<<1],to[N<<1],cnte;
ll ans;
inline void add(int u, int v){
	to[++cnte] = v;
	nxt[cnte] = head[u];
	head[u] = cnte;
}
inline void insert(char c, int idx){
	int p = las;
	las = ++tot;
	len[tot] = idx;
	for(; p && !son[p][c]; p = fa[p]) son[p][c] = las;
	if(!p){ fa[las] = 1; return; }
	int q = son[p][c];
	if(len[q] == len[p]+1){ fa[las] = q; return; }
	len[++tot] = len[p]+1;
	memcpy(son[tot],son[q],sizeof(son[q])), fa[tot] = fa[q];
	fa[q] = tot, fa[las] = tot;
	for(; son[p][c] == q; p = fa[p]) son[p][c] = tot;
}
void dfs(int u){
	sz[u] = 1;
	for(int i = head[u]; i; i = nxt[i]){
		dfs(to[i]);
		sz[u] += sz[to[i]];
	}
	ans += 1ll*sz[u]*(sz[u]+1)/2*(len[u]-len[fa[u]]);
}
int main(){
	// freopen("file.in","r",stdin);
	scanf("%s",s+1);
	n = strlen(s+1);
	las = tot = 1;
	for(int i = 1; i <= n; ++i){
		insert(s[i]-'a',i);
	}
	for(int i = 2; i <= tot; ++i){
		add(fa[i],i);
	}
	dfs(1);
	printf("%lld\n",ans);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

struct Node;
typedef Node* NP;
struct Node {
    NP go[26], suf;
    vector<NP> to;
    int up;
    ll dp;

    Node() {
        for (int i = 0; i < 26; i++) {
            go[i] = NULL;
        }
        suf = NULL;
        up = 0;
        dp = 0;
    }
};

Node pool[233333];
NP cr = pool;

NP root = new Node();
NP append(NP p, int w) {
    NP np = cr++;
    np->dp = 1;
    np->up = p->up+1;
    for (; p && !p->go[w]; p = p->suf) {
        p->go[w] = np;
    }
    if (!p) {
        np->suf = root;
    } else {
        NP q = p->go[w];
        if (p->up+1 == q->up) {
            np->suf = q;
        } else {
            NP nq = cr++;
            for (int i = 0; i < 26; i++) {
                nq->go[i] = q->go[i];
            }
            nq->up = p->up+1;
            nq->suf = q->suf;
            np->suf = q->suf = nq;
            for (; p && p->go[w] == q; p = p->suf) {
                p->go[w] = nq;
            }
        }
    }
    return np;
}

pair<ll, ll> dfs(NP v) {
    if (!v) return make_pair(ll(0), ll(0));
    ll dp = v->dp, sm = 0;
    for (int i = 0; i < int(v->to.size()); i++) {
        pair<ll, ll> u = dfs(v->to[i]);
        dp += u.first;
        sm += u.second;
    }
    if (v->suf) {
        int cnt = v->up - v->suf->up;
        sm += dp*(dp+1)/2*cnt;
    }
    return make_pair(dp, sm);
}

char buf[100010];

int main() {
    scanf("%s", buf);
    NP nw = root;
    for (int i = 0; buf[i]; i++) {
        nw = append(nw, buf[i]);
    }
    for (NP v = pool; v != cr; v++) {
        if (v->suf) v->suf->to.push_back(v);
    }
    cout << dfs(root).second << endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

struct Node;
typedef Node* NP;
struct Node {
    NP go[26], suf;
    vector<NP> to;
    int up;
    ll dp;

    Node() {
        for (int i = 0; i < 26; i++) {
            go[i] = NULL;
        }
        suf = NULL;
        up = 0;
        dp = 0;
    }
};

Node pool[233333];
NP cr = pool;

NP root = new Node();
NP append(NP p, int w) {
    NP np = cr++;
    np->dp = 1;
    np->up = p->up+1;
    for (; p && !p->go[w]; p = p->suf) {
        p->go[w] = np;
    }
    if (!p) {
        np->suf = root;
    } else {
        NP q = p->go[w];
        if (p->up+1 == q->up) {
            np->suf = q;
        } else {
            NP nq = cr++;
            for (int i = 0; i < 26; i++) {
                nq->go[i] = q->go[i];
            }
            nq->up = p->up+1;
            nq->suf = q->suf;
            np->suf = q->suf = nq;
            for (; p && p->go[w] == q; p = p->suf) {
                p->go[w] = nq;
            }
        }
    }
    return np;
}

pair<ll, ll> dfs(NP v) {
    if (!v) return make_pair(ll(0), ll(0));
    ll dp = v->dp, sm = 0;
    for (int i = 0; i < int(v->to.size()); i++) {
        pair<ll, ll> u = dfs(v->to[i]);
        dp += u.first;
        sm += u.second;
    }
    if (v->suf) {
        int cnt = v->up - v->suf->up;
        sm += dp*(dp+1)/2*cnt;
    }
    return make_pair(dp, sm);
}

char buf[100010];

int main() {
    scanf("%s", buf);
    NP nw = root;
    for (int i = 0; buf[i]; i++) {
        nw = append(nw, buf[i]-'a');
    }
    for (NP v = pool; v != cr; v++) {
        if (v->suf) v->suf->to.push_back(v);
    }
    printf("%lld\n", dfs(root).second);
    return 0;
}


#include <bits/stdc++.h>
#define ud unsigned int
#define ll long long
#define ull unsigned long long
#define MAX_INF 0x3f
#define MAX_INF_VAL 0x3f3f3f3f
#define MAX_INF_VAL_LL 0x3f3f3f3f3f3f3f3f
#define pi 3.141592653589
#define eps 1e-8
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
//#define p 2173412051LL
//#define sz 2

template< typename T > void read( T &x ) {
	x = 0;
	char ch = getchar();
	ll f = 1;
	while( !isdigit( ch ) ) {
		if( ch == '-' )
		f *= -1;
		ch = getchar();
	}
	while( isdigit( ch ) ) {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	x *= f;
}

using namespace std;

const int N = 100010;

struct p {
	int x, v;
};
char s[ N ];
int sa[ N ], rk[ N << 1 ], oldrk[ N << 1 ], cnt[ N ], id[ N ], tmp[ N ];
int height[ N ];
p st[ N ];

bool cmp( int, int, int );
void suf_arr( char*, int*, int*, int*, int n, int m );

int main() {
	int n;
	int tail;
	ll ans;
	scanf( "%s", s + 1 );
	n = strlen( s + 1 );
	suf_arr( s, sa, rk, height, n, 300 );
	height[ n + 1 ] = 0;
	tail = 0;
	ans = 1LL * n * ( n + 1 ) / 2;
	for( int i = 1; i <= n + 1; ++i ) {
		int tmp = height[ i ], lst = i;
		while( tail && st[ tail - 1 ].v > tmp ) {
			int xl = st[ tail - 1 ].x - 1, xr = i - 1, xlen = xr - xl + 1;
			int vl = max( st[ tail - 2 ].v, tmp ) + 1, vr = st[ tail - 1 ].v, vlen = vr - vl + 1;
			ans += 1LL * ( xlen * ( xlen + 1 ) / 2 - xlen ) * vlen;
			lst = st[ tail - 1 ].x;
			--tail;
		}
		if( tail && st[ tail - 1 ].v == tmp )
			continue;
		st[ tail++ ] = { lst, tmp };
	}
	printf( "%lld", ans );
	return 0;
}

bool cmp( int x, int y, int w ) {
	return oldrk[ x ] == oldrk[ y ] && oldrk[ x + w ] == oldrk[ y + w ];
}

void suf_arr( char* s, int* sa, int* rk, int* height, int n, int m ) {
	int p;
	memset( cnt, 0, ( m + 1 ) * sizeof( int ) );
	memset( oldrk, 0, ( 2 * n + 1 ) * sizeof( int ) );
	for( int i = 1; i <= n; ++i )
		++cnt[ rk[ i ] = s[ i ] ];
	for( int i = 1; i <= m; ++i )
		cnt[ i ] += cnt[ i - 1 ];
	for( int i = 1; i <= n; ++i )
		sa[ cnt[ rk[ i ] ]-- ] = i;
	for( int w = 1, p = 0; w < n; w <<= 1, m = p, p = 0 ) {
		for( int i = n - w + 1; i <= n; ++i )
			id[ ++p ] = i;
		for( int i = 1; i <= n; ++i ) {
			if( sa[ i ] > w )
				id[ ++p ] = sa[ i ] - w;
		}
		memset( cnt, 0, ( m + 1 ) * sizeof( int ) );
		for( int i = 1; i <= n; ++i )
			++cnt[ tmp[ i ] = rk[ id[ i ] ] ];
		for( int i = 1; i <= m; ++i )
			cnt[ i ] += cnt[ i - 1 ];
		for( int i = n; i; --i )
			sa[ cnt[ tmp[ i ] ]-- ] = id[ i ];
		memcpy( oldrk, rk, ( n + 1 ) * sizeof( int ) );
		p = 0;
		for( int i = 1; i <= n; ++i )
			rk[ sa[ i ] ] = cmp( sa[ i ], sa[ i - 1 ], w )? p: ++p;
	}
	for( int i = 1, k = 0; i <= n; ++i ) {
		if( k )
			--k;
		while( s[ i + k ] == s[ sa[ rk[ i ] - 1 ] + k ] )
			++k;
		height[ rk[ i ] ] = k;
	}
}


#include <bits/stdc++.h>
#define ud unsigned int
#define ll long long
#define ull unsigned long long
#define MAX_INF 0x3f
#define MAX_INF_VAL 0x3f3f3f3f
#define MAX_INF_VAL_LL 0x3f3f3f3f3f3f3f3f
#define pi 3.141592653589
#define eps 1e-8
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
//#define p 2173412051LL
//#define sz 2

template< typename T > void read( T &x ) {
	x = 0;
	char ch = getchar();
	ll f = 1;
	while( !isdigit( ch ) ) {
		if( ch == '-' )
		f *= -1;
		ch = getchar();
	}
	while( isdigit( ch ) ) {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	x *= f;
}

using namespace std;

const int N = 100010;

struct p {
	int x, v;
};
char s[ N ];
int sa[ N ], rk[ N << 1 ], oldrk[ N << 1 ], cnt[ N ], id[ N ], tmp[ N ];
int height[ N ];
p st[ N ];

bool cmp( int, int, int );
void suf_arr( char*, int*, int*, int*, int n, int m );

int main() {
	int n;
	int tail;
	ll ans;
	scanf( "%s", s + 1 );
	n = strlen( s + 1 );
	suf_arr( s, sa, rk, height, n, 300 );
	height[ n + 1 ] = 0;
	tail = 0;
	ans = 1LL * n * ( n + 1 ) / 2;
	for( int i = 1; i <= n + 1; ++i ) {
		int tmp = height[ i ], lst = i;
		while( tail && st[ tail - 1 ].v > tmp ) {
			int xl = st[ tail - 1 ].x - 1, xr = i - 1, xlen = xr - xl + 1;
			int vl = max( st[ tail - 2 ].v, tmp ) + 1, vr = st[ tail - 1 ].v, vlen = vr - vl + 1;
			ans += ( 1LL * xlen * ( xlen + 1 ) / 2 - xlen ) * vlen;
			lst = st[ tail - 1 ].x;
			--tail;
		}
		if( tail && st[ tail - 1 ].v == tmp )
			continue;
		st[ tail++ ] = { lst, tmp };
	}
	printf( "%lld", ans );
	return 0;
}

bool cmp( int x, int y, int w ) {
	return oldrk[ x ] == oldrk[ y ] && oldrk[ x + w ] == oldrk[ y + w ];
}

void suf_arr( char* s, int* sa, int* rk, int* height, int n, int m ) {
	int p;
	memset( cnt, 0, ( m + 1 ) * sizeof( int ) );
	memset( oldrk, 0, ( 2 * n + 1 ) * sizeof( int ) );
	for( int i = 1; i <= n; ++i )
		++cnt[ rk[ i ] = s[ i ] ];
	for( int i = 1; i <= m; ++i )
		cnt[ i ] += cnt[ i - 1 ];
	for( int i = 1; i <= n; ++i )
		sa[ cnt[ rk[ i ] ]-- ] = i;
	for( int w = 1, p = 0; w < n; w <<= 1, m = p, p = 0 ) {
		for( int i = n - w + 1; i <= n; ++i )
			id[ ++p ] = i;
		for( int i = 1; i <= n; ++i ) {
			if( sa[ i ] > w )
				id[ ++p ] = sa[ i ] - w;
		}
		memset( cnt, 0, ( m + 1 ) * sizeof( int ) );
		for( int i = 1; i <= n; ++i )
			++cnt[ tmp[ i ] = rk[ id[ i ] ] ];
		for( int i = 1; i <= m; ++i )
			cnt[ i ] += cnt[ i - 1 ];
		for( int i = n; i; --i )
			sa[ cnt[ tmp[ i ] ]-- ] = id[ i ];
		memcpy( oldrk, rk, ( n + 1 ) * sizeof( int ) );
		p = 0;
		for( int i = 1; i <= n; ++i )
			rk[ sa[ i ] ] = cmp( sa[ i ], sa[ i - 1 ], w )? p: ++p;
	}
	for( int i = 1, k = 0; i <= n; ++i ) {
		if( k )
			--k;
		while( s[ i + k ] == s[ sa[ rk[ i ] - 1 ] + k ] )
			++k;
		height[ rk[ i ] ] = k;
	}
}


#include <bits/stdc++.h>
#define ud unsigned int
#define ll long long
#define ull unsigned long long
#define MAX_INF 0x3f
#define MAX_INF_VAL 0x3f3f3f3f
#define MAX_INF_VAL_LL 0x3f3f3f3f3f3f3f3f
#define pi 3.141592653589
#define eps 1e-8
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
//#define p 2173412051LL
//#define sz 2

template< typename T > void read( T &x ) {
	x = 0;
	char ch = getchar();
	ll f = 1;
	while( !isdigit( ch ) ) {
		if( ch == '-' )
		f *= -1;
		ch = getchar();
	}
	while( isdigit( ch ) ) {
		x = x * 10 + ch - 48;
		ch = getchar();
	}
	x *= f;
}

using namespace std;

const int N = 100010;

struct p {
	int x, v;
};
char s[ N ];
int sa[ N ], rk[ N << 1 ], oldrk[ N << 1 ], cnt[ N ], id[ N ], tmp[ N ];
int height[ N ];
p st[ N ];

bool cmp( int, int, int );
void suf_arr( char*, int*, int*, int*, int n, int m );

int main() {
	int n;
	int tail;
	ll ans;
	scanf( "%s", s + 1 );
	n = strlen( s + 1 );
	suf_arr( s, sa, rk, height, n, 300 );
	height[ n + 1 ] = 0;
	tail = 0;
	ans = 1LL * n * ( n + 1 ) / 2;
	for( int i = 1; i <= n + 1; ++i ) {
		int tmp = height[ i ], lst = i;
		while( tail && st[ tail - 1 ].v > tmp ) {
		    assert( tail >= 2 );
			int xl = st[ tail - 1 ].x - 1, xr = i - 1, xlen = xr - xl + 1;
			int vl = max( st[ tail - 2 ].v, tmp ) + 1, vr = st[ tail - 1 ].v, vlen = vr - vl + 1;
			ans += ( 1LL * xlen * ( xlen + 1 ) / 2 - xlen ) * vlen;
			lst = st[ tail - 1 ].x;
			--tail;
		}
		if( tail && st[ tail - 1 ].v == tmp )
			continue;
		st[ tail++ ] = { lst, tmp };
	}
	printf( "%lld", ans );
	return 0;
}

bool cmp( int x, int y, int w ) {
	return oldrk[ x ] == oldrk[ y ] && oldrk[ x + w ] == oldrk[ y + w ];
}

void suf_arr( char* s, int* sa, int* rk, int* height, int n, int m ) {
	int p;
	memset( cnt, 0, ( m + 1 ) * sizeof( int ) );
	memset( oldrk, 0, ( 2 * n + 1 ) * sizeof( int ) );
	for( int i = 1; i <= n; ++i )
		++cnt[ rk[ i ] = s[ i ] ];
	for( int i = 1; i <= m; ++i )
		cnt[ i ] += cnt[ i - 1 ];
	for( int i = 1; i <= n; ++i )
		sa[ cnt[ rk[ i ] ]-- ] = i;
	for( int w = 1, p = 0; w < n; w <<= 1, m = p, p = 0 ) {
		for( int i = n - w + 1; i <= n; ++i )
			id[ ++p ] = i;
		for( int i = 1; i <= n; ++i ) {
			if( sa[ i ] > w )
				id[ ++p ] = sa[ i ] - w;
		}
		memset( cnt, 0, ( m + 1 ) * sizeof( int ) );
		for( int i = 1; i <= n; ++i )
			++cnt[ tmp[ i ] = rk[ id[ i ] ] ];
		for( int i = 1; i <= m; ++i )
			cnt[ i ] += cnt[ i - 1 ];
		for( int i = n; i; --i )
			sa[ cnt[ tmp[ i ] ]-- ] = id[ i ];
		memcpy( oldrk, rk, ( n + 1 ) * sizeof( int ) );
		p = 0;
		for( int i = 1; i <= n; ++i )
			rk[ sa[ i ] ] = cmp( sa[ i ], sa[ i - 1 ], w )? p: ++p;
	}
	for( int i = 1, k = 0; i <= n; ++i ) {
		if( k )
			--k;
		while( s[ i + k ] == s[ sa[ rk[ i ] - 1 ] + k ] )
			++k;
		height[ rk[ i ] ] = k;
	}
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
	ll a=0,b=getchar(),c=1;
	while(!isdigit(b))c=b=='-'?-1:1,b=getchar();
	while(isdigit(b))a=a*10+b-'0',b=getchar();
	return a*c;
}
const int N=1e5+9,M=97;
string s;
int a[N],n,k,ab,b[N],c[N],d[N];
ll ans,sum;
bool gao(int i,int j){
	if(c[i]!=c[j])
		return c[i]<c[j];
	i+=ab,j+=ab;
	return (i<n and j<n)?c[i]<c[j]:i>j;
}
vector<pair<int,int> > l;
int main(){
	cin >> s,n=s.size();
	for(int i=0;i<n;i++)
		b[i]=i,c[i]=s[i];
	for(ab=1;;ab*=2){
		sort(b,b+n,gao);
		for(int i=0;i<n-1;i++)
			d[i+1]=d[i]+gao(b[i],b[i+1]);
		for(int i=0;i<n;i++)
			c[b[i]]=d[i];
		if(d[n-1]==n-1)break;
	}
	for(int i=0,k=0;i<n;i++)
		if(c[i]!=n-1){
			for(int j=b[c[i]+1];s[i+k]==s[j+k];)
				k++;
			a[c[i]]=k;
			if(k)k--;
		}
	for(int i=0;i<n-1;i++){
		int t=1;
		while(l.size() and l.back().first>=a[i])
			sum-=1ll*l.back().second*l.back().first,t+=l.back().second,l.pop_back();
		sum+=1ll*a[i]*t;
		ans+=sum;
		l.push_back({a[i],t});
	}
	cout << ans+1ll*n*(n+1)/2;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
	ll a=0,b=getchar(),c=1;
	while(!isdigit(b))c=b=='-'?-1:1,b=getchar();
	while(isdigit(b))a=a*10+b-'0',b=getchar();
	return a*c;
}
const int N=1e5+9,M=97;
string s;
int a[N],n,k,ab,b[N],c[N],d[N];
ll ans,sum;
bool gao(int i,int j){
	if(c[i]!=c[j])
		return c[i]<c[j];
	i+=ab,j+=ab;
	return (i<n and j<n)?c[i]<c[j]:i>j;
}
vector<pair<int,int> > l;
int main(){
	cin >> s,n=s.size();
	for(int i=0;i<n;i++)
		b[i]=i,c[i]=s[i];
	for(ab=1;;ab*=2){
		sort(b,b+n,gao);
		for(int i=0;i<n-1;i++)
			d[i+1]=d[i]+gao(b[i],b[i+1]);
		for(int i=0;i<n;i++)
			c[b[i]]=d[i];
		if(d[n-1]==n-1)break;
	}
	for(int i=0,k=0;i<n;i++)
		if(c[i]!=n-1){
			for(int j=b[c[i]+1];s[i+k]==s[j+k];)
				k++;
			a[c[i]]=k;
			if(k)k--;
		}
	for(int i=0;i<n-1;i++){
		int t=1;
		while(l.size() and l.back().first>=a[i])
			sum-=1ll*l.back().second*l.back().first,t+=l.back().second,l.pop_back();
		sum+=1ll*a[i]*t;
		ans+=sum;
		l.push_back({a[i],t});
	}
	cout << ans+1ll*n*(n+1+n/1000)/2;
	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int dis[MAXN],fa[MAXN],ch[MAXN][26];
ll sz[MAXN];
char str[MAXN];
int rt,cnt,cur;
void built(int x){
    int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;sz[cur]=1;
    for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur;
    if(!p)fa[cur]=rt;
    else{
	int q=ch[p][x];
	if(dis[q]==dis[p]+1)fa[cur]=q;
	else{
	    int nt=++cnt;dis[nt]=dis[p]+1;
	    memcpy(ch[nt],ch[q],sizeof(ch[q]));
	    fa[nt]=fa[q];fa[q]=fa[cur]=nt;
	    for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt;
	}
    }
}
ll ans;
void dfs(int x){
    link(x){
	dfs(j->t);
	sz[x]+=sz[j->t];
    }
    ans+=1ll*(dis[x]-dis[fa[x]])*((1ll*sz[x]+1)*sz[x]/2);
}

int main(){
    scanf("%s",str);
    int len=strlen(str);
    rt=cur=cnt=1;
    inc(i,0,len-1)built(str[i]-'a');
    inc(i,1,cnt)add(fa[i],i);
    ans=0;
    dfs(rt);
    printf("%lld\n",ans);
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int dis[MAXN],fa[MAXN],ch[MAXN][26],sz[MAXN];
char str[MAXN];
int rt,cnt,cur;
void built(int x){
    int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;sz[cur]=1;
    for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur;
    if(!p)fa[cur]=rt;
    else{
	int q=ch[p][x];
	if(dis[q]==dis[p]+1)fa[cur]=q;
	else{
	    int nt=++cnt;dis[nt]=dis[p]+1;
	    memcpy(ch[nt],ch[q],sizeof(ch[q]));
	    fa[nt]=fa[q];fa[q]=fa[cur]=nt;
	    for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt;
	}
    }
}
ll ans;
void dfs(int x){
    link(x){
	dfs(j->t);
	sz[x]+=sz[j->t];
    }
    ans+=1ll*(dis[x]-dis[fa[x]])*((sz[x]+1)*sz[x]/2);
}

int main(){
    scanf("%s",str);
    int len=strlen(str);
    rt=cur=cnt=1;
    inc(i,0,len-1)built(str[i]-'a');
    inc(i,1,cnt)add(fa[i],i);
    ans=0;
    dfs(rt);
    printf("%lld\n",ans);
}


#include<bits/stdc++.h>
typedef long long LL;
const LL maxn=2e5+9;
LL n,lst,nod,num,ans;
LL son[maxn][26],fail[maxn],len[maxn],size[maxn],head[maxn];
char s[maxn];
void Insert(LL c){
	LL np(++nod),p(lst); len[np]=len[p]+1;
	lst=np;
	while(p && !son[p][c]){ son[p][c]=np; p=fail[p]; }
	if(!p) fail[np]=1;
	else{
		LL q(son[p][c]);
		if(len[q]==len[p]+1){ fail[np]=q; }
		else{
			LL nq(++nod); len[nq]=len[p]+1; fail[nq]=fail[q]; fail[q]=fail[np]=nq;
			memcpy(son[nq],son[q],sizeof(son[q]));
			while(p && son[p][c]==q){ son[p][c]=nq; p=fail[p]; }
		}
	}
	size[np]=1;
}
struct node{
	LL to,nxt;
}dis[maxn];
void Add(LL u,LL v){ dis[++num]=(node){v,head[u]}; head[u]=num; }
void Dfs(LL u,LL f){
	for(LL i=head[u];i;i=dis[i].nxt){
		LL v(dis[i].to); Dfs(v,u); size[u]+=size[v];
	}
	ans+=(len[u]-len[f])*((size[u]+1)*size[u]/2);
}
int main(){
	scanf("%s",s+1); n=strlen(s+1);
	lst=nod=1;
	for(LL i=1;i<=n;++i)
		Insert(s[i]-'a');
	for(LL i=1;i<=nod;++i) if(fail[i]) Add(fail[i],i);
	Dfs(1,0);
	printf("%lld\n",ans);
	return 0;
}


#include<bits/stdc++.h>
typedef long long LL;
const LL maxn=2e5+9;
LL n,lst,nod,num,ans;
LL son[maxn][26],fail[maxn],len[maxn],size[maxn],head[maxn];
char s[maxn];
void Insert(LL c){
	LL np(++nod),p(lst); len[np]=len[p]+1;
	lst=np;
	while(p && !son[p][c]){ son[p][c]=np; p=fail[p]; }
	if(son[p][c]){
		LL q(son[p][c]);
		if(len[q]==len[p]+1){ fail[np]=q; }
		else{
			LL nq(++nod); len[nq]=len[p]+1; fail[nq]=fail[q]; fail[q]=fail[np]=nq;
			memcpy(son[nq],son[q],sizeof(q));
			while(p && son[p][c]==q){ son[p][c]=nq; p=fail[p]; }
		}
	}else fail[np]=1;
	size[np]=1;
}
struct node{
	LL to,nxt;
}dis[maxn];
void Add(LL u,LL v){ dis[++num]=(node){v,head[u]}; head[u]=num; }
void Dfs(LL u,LL f){
//	printf("(%lld,%lld)\n",f,u);
//	size[u]=1;
	for(LL i=head[u];i;i=dis[i].nxt){
		LL v(dis[i].to); Dfs(v,u); size[u]+=size[v];
	}
	ans+=(len[u]-len[f])*((size[u]+1)*size[u]/2);
}
int main(){
	scanf("%s",s+1); n=strlen(s+1);
	lst=nod=1;
	for(LL i=1;i<=n;++i){
		Insert(s[i]-'a'); //pos[lst]=i;
	}
//	for(LL i=1;i<=)
	for(LL i=1;i<=nod;++i) if(fail[i]) Add(fail[i],i);
	Dfs(1,0);
	printf("%lld\n",ans);
	return 0;
}


#include<bits/stdc++.h>
typedef long long LL;
const LL maxn=2e5+9;
LL n,lst,nod,num,ans;
LL son[maxn][26],fail[maxn],len[maxn],size[maxn],head[maxn];
char s[maxn];
void Insert(LL c){
	LL np(++nod),p(lst); len[np]=len[p]+1;
	lst=np;
	while(p && !son[p][c]){ son[p][c]=np; p=fail[p]; }
	if(son[p][c]){
		LL q(son[p][c]);
		if(len[q]==len[p]+1){ fail[np]=q; }
		else{
			LL nq(++nod); len[nq]=len[p]+1; fail[nq]=fail[q]; fail[q]=fail[np]=nq;
			memcpy(son[nq],son[q],sizeof(q));
			while(p && son[p][c]==q){ son[p][c]=nq; p=fail[p]; }
		}
	}else fail[np]=1;
}
struct node{
	LL to,nxt;
}dis[maxn];
void Add(LL u,LL v){ dis[++num]=(node){v,head[u]}; head[u]=num; }
void Dfs(LL u,LL f){
//	printf("(%lld,%lld)\n",f,u);
	size[u]=1;
	for(LL i=head[u];i;i=dis[i].nxt){
		LL v(dis[i].to); Dfs(v,u); size[u]+=size[v];
	}
	ans+=(len[u]-len[f])*((size[u]+1)*size[u]/2);
}
int main(){
	scanf("%s",s+1); n=strlen(s+1);
	lst=nod=1;
	for(LL i=1;i<=n;++i){
		Insert(s[i]-'a'); //pos[lst]=i;
	}
	for(LL i=1;i<=nod;++i) if(fail[i]) Add(fail[i],i);
	Dfs(1,0);
	printf("%lld\n",ans);
	return 0;
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}
#define maxn 2000005
char s[maxn];
int l,tot=1,lst=1;
int ch[maxn][26],len[maxn],fail[maxn];
int sz[maxn];
void append(int c)
{
	int u=++tot,p=lst;
	len[u]=len[p]+1,sz[tot]=1;
	for(;p&&!ch[p][c];p=fail[p])ch[p][c]=u;
	if(!p)fail[u]=1;
	else{
		int q=ch[p][c];
		if(len[q]==len[p]+1)fail[u]=q;
		else{
			int cc=++tot;
			fail[cc]=fail[q],len[cc]=len[p]+1;
			memcpy(ch[cc],ch[q],sizeof(ch[cc]));
			for(;p&&ch[p][c]==q;p=fail[p])ch[p][c]=cc;
			fail[q]=fail[u]=cc;
		}
	}lst=u;
}

long long res;
struct edge{
	int to,nxt;
}e[maxn];
int cnt,head[maxn];
inline void adde(int u,int v){
	e[++cnt]=(edge){v,head[u]};
	head[u]=cnt;
}
void dfs(int u)
{
	for(int i=head[u];i;i=e[i].nxt){
		dfs(e[i].to);
		sz[u]+=sz[e[i].to];
	}
	res+=1ll*sz[u]*(sz[u]+1)/2*(len[u]-len[fail[u]]);
}
signed main()
{
	cin>>s;
	l=strlen(s);
	For(i,0,l-1)append(s[i]-'a');
	For(i,2,tot)adde(fail[i],i);
	dfs(1);
	cout<<res;
    return 0;
}


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
#define int long long
using namespace std;
inline int read()
{
    char c=getchar();int x=0;bool f=0;
    for(;!isdigit(c);c=getchar())f^=!(c^45);
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    if(f)x=-x;return x;
}
#define maxn 2000005
char s[maxn];
int l,tot=1,lst=1;
int ch[maxn][26],len[maxn],fail[maxn];
int sz[maxn];
void append(int c)
{
	int u=++tot,p=lst;
	len[u]=len[p]+1,sz[tot]=1;
	for(;p&&!ch[p][c];p=fail[p])ch[p][c]=u;
	if(!p)fail[u]=1;
	else{
		int q=ch[p][c];
		if(len[q]==len[p]+1)fail[u]=q;
		else{
			int cc=++tot;
			fail[cc]=fail[q],len[cc]=len[p]+1;
			memcpy(ch[cc],ch[q],sizeof(ch[cc]));
			for(;p&&ch[p][c]==q;p=fail[p])ch[p][c]=cc;
			fail[q]=fail[u]=cc;
		}
	}lst=u;
}

int res;
struct edge{
	int to,nxt;
}e[maxn];
int cnt,head[maxn];
inline void adde(int u,int v){
	e[++cnt]=(edge){v,head[u]};
	head[u]=cnt;
}
void dfs(int u)
{
	for(int i=head[u];i;i=e[i].nxt){
		dfs(e[i].to);
		sz[u]+=sz[e[i].to];
	}
	res+=sz[u]*(sz[u]+1)/2*(len[u]-len[fail[u]]);
}
signed main()
{
	cin>>s;
	l=strlen(s);
	For(i,0,l-1)append(s[i]-'a');
	For(i,2,tot)adde(fail[i],i);
	dfs(1);
	cout<<res;
    return 0;
}


/*
I'm a blind man
I'm a blind man
And my world is pale
When a blind man cries
Lord, you know
There ain't a sadder tale
*/
#include <bits/stdc++.h>

using namespace std;

typedef long long int ll;
typedef pair<ll, ll> pll;

#define sz(x)                       (ll) x.size()
#define all(x)                      (x).begin(),(x).end()
#define F                           first
#define S                           second

ll Pow(ll a, ll b, ll md, ll ans = 1) {
    for (; b; b >>= 1, a = a * a % md)
        if (b & 1)
            ans = ans * a % md;
    return ans % md;
}
const ll MAXN = 1e5 + 10;
const ll LOG  = 22;
const ll INF  = 8e18;
const ll MOD  = 1e9 + 7;
char C[MAXN]; vector<ll> lcp[MAXN];
ll R[LOG][MAXN], P[MAXN], Pr[MAXN], SZ[MAXN], n, ans, res;
// Hear me grieving, lying on the floor
void BuildSuffixArray() {
	for (ll i = 1; i <= n; i++) R[0][i] = C[i], P[i] = i;
	for (ll pw = 1; pw < LOG; pw++) {
  		auto cmp = [&] (ll x, ll y) {
  			if (R[pw - 1][x] != R[pw - 1][y]) return R[pw - 1][x] < R[pw - 1][y];
  			if (max(x, y) + (1 << (pw - 1)) > n) return x > y;
  			return R[pw - 1][x + (1 << (pw - 1))] < R[pw - 1][y + (1 << (pw - 1))];
  		};
    	sort(P + 1, P + n + 1, cmp);
    	R[pw][P[1]] = 1;
    	for (ll i = 2; i <= n; i++)
    		R[pw][P[i]] = R[pw][P[i - 1]] + cmp(P[i - 1], P[i]);
	}
}

ll LCP(ll x, ll y) {
 	if (x > y) swap(x, y);
  	ll tes = 0;
  	for (ll i = LOG - 1; i >= 0; i--)
  		if (R[i][x] == R[i][y]) {
      		tes |= (1 << i);
      		x += (1 << i), y += (1 << i);
  	}
  	return tes;
}

ll C2(ll x) {
	return x * (x + 1) / 2;
}

ll Find(ll v) { return Pr[v] == -1 ? v : Pr[v] = Find(Pr[v]); };

void Union(ll u, ll v) {
	v = Find(v), u = Find(u);
	if (u == v) return;
	Pr[u] = v;
	res -= C2(SZ[u]), res -= C2(SZ[v]);
	SZ[v] += SZ[u];
	res += C2(SZ[v]);
}

int main() {
	fill(Pr, Pr + MAXN, -1);
	fill(SZ, SZ + MAXN, 1);
	scanf("%s", C + 1); n = strlen(C + 1);
	BuildSuffixArray();
	for (ll i = 1; i < n; i++) {
		lcp[LCP(P[i], P[i + 1])].push_back(i);
	}
	for (ll i = n; ~i; i--) {
		for (ll j : lcp[i]) Union(j, j + 1);
		ans += res;
	}
	printf("%lld\n", ans + n);
    return 0;
}


#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define dprint(v) cerr << #v"=" << v << endl //;)
#define forr(i,a,b) for(int i=(a); i<(b); i++)
#define forn(i,n) forr(i,0,n)
#define dforn(i,n) for(int i=n-1; i>=0; i--)
#define forall(it,v) for(auto it=v.begin();it!=v.end();++it)
#define sz(c) ((int)c.size())
#define zero(v) memset(v, 0, sizeof(v))
#define pb push_back
#define fst first
#define snd second
typedef long long ll;
typedef pair<int,int> ii;

int n;

struct St {
    int len;
    St *link;
    map<char,St*> next;
    bool terminal;
    ll dp;
    ll dp2;
    St(int len, St* link=NULL):len(len),link(link), terminal(0), dp(-1), dp2(-1) {}
    inline ll count_paths_to_term(){
        if(dp!=-1) return dp;
        ll &r=dp;
        r=terminal;
        //~ cout << terminal <<  ' ' << sz(next) << endl;
        forall(it, next)
            r+=it->snd->count_paths_to_term();
        return r;
    }

    inline ll solve(bool prim=true){
        ll r=dp2;
        if(r!=-1) return r;
        dp2=-9999;
        r=0;
        ll r2=prim?0:count_paths_to_term();
        r2=r2+(r2*(r2-1))/2;
        //~ dprint(r);
        forall(it, next)
            r+=it->snd->solve(false);
        return dp2=r+r2;

    }
};
struct SuA{
    St *init, *last;
    SuA(): init(new St(0)), last(init) {}
    inline void extend(char c){
        St *cur=new St(last->len+1, init), *p=last;
        for(;p && !p->next.count(c); p=p->link) p->next[c]=cur;
        if(p){
            St *q=p->next[c];
            if(p->len+1==q->len) cur->link=q;
            else{
                St *clone = new St(p->len+1, q->link);
                clone->next = q->next;
                for(;p && p->next.count(c) && p->next[c]==q; p=p->link)
                    p->next[c] = clone;
                q->link = cur->link = clone;
            }
        }
        last = cur;
    }
    St *go(string s){//run automata
        St *p=init;
        forall(it, s){
            if(!p->next.count(*it)) return NULL;
            p=p->next[*it];
        }
        return p;
    }
    void markterms(){
        for(St *p=last; p; p=p->link) p->terminal=true;
    }
}aut;

char s[100100];

int main() {
	//~ freopen("input.in", "r", stdin);
    ios::sync_with_stdio(0);
    while(cin >> s){
        n=strlen(s);
        aut=SuA();
        forn(i, n) aut.extend(s[i]);
        aut.markterms();//para cantidad de veces
        cout << aut.init->solve() << endl;
    }

	return 0;
}


#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define dprint(v) cerr << #v"=" << v << endl //;)
#define forr(i,a,b) for(int i=(a); i<(b); i++)
#define forn(i,n) forr(i,0,n)
#define dforn(i,n) for(int i=n-1; i>=0; i--)
#define forall(it,v) for(auto it=v.begin();it!=v.end();++it)
#define sz(c) ((int)c.size())
#define zero(v) memset(v, 0, sizeof(v))
#define pb push_back
#define fst first
#define snd second
typedef long long ll;
typedef pair<int,int> ii;

int n;

struct St {
    int len;
    St *link;
    map<char,St*> next;
    bool terminal;
    ll dp;
    ll dp2;
    St(int len, St* link=NULL):len(len),link(link), terminal(0), dp(-1), dp2(-1) {}
    inline ll count_paths_to_term(){
        if(dp!=-1) return dp;
        ll &r=dp;
        r=terminal;
        //~ cout << terminal <<  ' ' << sz(next) << endl;
        forall(it, next)
            r+=it->snd->count_paths_to_term();
        return r;
    }

    inline ll solve(bool prim=true){
        ll r=dp2;
        if(r!=-1) return r;
        dp2=-9999;
        r=0;
        ll r2=prim?0:count_paths_to_term();
        r2=r2+(r2*(r2-1))/2;
        //~ dprint(r);
        forall(it, next)
            r+=it->snd->solve(false);
        return dp2=r+r2;

    }
};
struct SuA{
    St *init, *last;
    SuA(): init(new St(0)), last(init) {}
    inline void extend(char c){
        St *cur=new St(last->len+1, init), *p=last;
        for(;p && !p->next.count(c); p=p->link) p->next[c]=cur;
        if(p){
            St *q=p->next[c];
            if(p->len+1==q->len) cur->link=q;
            else{
                St *clone = new St(p->len+1, q->link);
                clone->next = q->next;
                for(;p && p->next.count(c) && p->next[c]==q; p=p->link)
                    p->next[c] = clone;
                q->link = cur->link = clone;
            }
        }
        last = cur;
    }
    St *go(string s){//run automata
        St *p=init;
        forall(it, s){
            if(!p->next.count(*it)) return NULL;
            p=p->next[*it];
        }
        return p;
    }
    void markterms(){
        for(St *p=last; p; p=p->link) p->terminal=true;
    }
}aut;

char s[100100];

int main() {
	//~ freopen("input.in", "r", stdin);
    ios::sync_with_stdio(0);
    while(scanf("%s", s)>0){
        n=strlen(s);
        aut=SuA();
        forn(i, n) aut.extend(s[i]);
        aut.markterms();//para cantidad de veces
        printf("%I64d\n", aut.init->solve() );
    }

	return 0;
}


#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define dprint(v) cerr << #v"=" << v << endl //;)
#define forr(i,a,b) for(int i=(a); i<(b); i++)
#define forn(i,n) forr(i,0,n)
#define dforn(i,n) for(int i=n-1; i>=0; i--)
#define forall(it,v) for(auto it=v.begin();it!=v.end();++it)
#define sz(c) ((int)c.size())
#define zero(v) memset(v, 0, sizeof(v))
#define pb push_back
#define fst first
#define snd second
typedef long long ll;
typedef pair<int,int> ii;

int n;

struct St {
    int len;
    St *link;
    unordered_map<char,St*> next;
    bool terminal;
    ll dp;
    St(int len, St* link=NULL):len(len),link(link), terminal(0), dp(-1) {}
    inline ll count_paths_to_term(){
        if(dp!=-1) return dp;
        ll &r=dp;
        r=terminal;
        //~ cout << terminal <<  ' ' << sz(next) << endl;
        forall(it, next)
            r+=it->snd->count_paths_to_term();
        return r;
    }

    inline ll solve(bool prim=true){
        ll r=prim?0:count_paths_to_term();
        //~ dprint(s);
        //~ dprint(r);
        r=r+(r*(r-1))/2;
        //~ dprint(r);
        forall(it, next)
            r+=it->snd->solve(false);
        return r;

    }
};
struct SuA{
    St *init, *last;
    SuA(): init(new St(0)), last(init) {}
    inline void extend(char c){
        St *cur=new St(last->len+1, init), *p=last;
        for(;p && !p->next.count(c); p=p->link) p->next[c]=cur;
        if(p){
            St *q=p->next[c];
            if(p->len+1==q->len) cur->link=q;
            else{
                St *clone = new St(p->len+1, q->link);
                clone->next = q->next;
                for(;p && p->next.count(c) && p->next[c]==q; p=p->link)
                    p->next[c] = clone;
                q->link = cur->link = clone;
            }
        }
        last = cur;
    }
    St *go(string s){//run automata
        St *p=init;
        forall(it, s){
            if(!p->next.count(*it)) return NULL;
            p=p->next[*it];
        }
        return p;
    }
    void markterms(){
        for(St *p=last; p; p=p->link) p->terminal=true;
    }
}aut;

char s[100100];

int main() {
	//~ freopen("input.in", "r", stdin);
    ios::sync_with_stdio(0);
    while(scanf("%s", s)>0){
        n=strlen(s);
        aut=SuA();
        forn(i, n) aut.extend(s[i]);
        aut.markterms();//para cantidad de veces
        printf("%I64d\n", aut.init->solve() );
    }

	return 0;
}


#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define dprint(v) cerr << #v"=" << v << endl //;)
#define forr(i,a,b) for(int i=(a); i<(b); i++)
#define forn(i,n) forr(i,0,n)
#define dforn(i,n) for(int i=n-1; i>=0; i--)
#define forall(it,v) for(auto it=v.begin();it!=v.end();++it)
#define sz(c) ((int)c.size())
#define zero(v) memset(v, 0, sizeof(v))
#define pb push_back
#define fst first
#define snd second
typedef long long ll;
typedef pair<int,int> ii;

int n;

struct St {
    int len;
    St *link;
    unordered_map<char,St*> next;
    bool terminal;
    ll dp;
    ll dp2;
    St(int len, St* link=NULL):len(len),link(link), terminal(0), dp(-1), dp2(-1) {}
    inline ll count_paths_to_term(){
        if(dp!=-1) return dp;
        ll &r=dp;
        r=terminal;
        //~ cout << terminal <<  ' ' << sz(next) << endl;
        forall(it, next)
            r+=it->snd->count_paths_to_term();
        return r;
    }

    inline ll solve(bool prim=true){
        ll r=dp2;
        if(r!=-1) return r;
        dp2=-9999;
        r=0;
        ll r2=prim?0:count_paths_to_term();
        r2=r2+(r2*(r2-1))/2;
        //~ dprint(r);
        forall(it, next)
            r+=it->snd->solve(false);
        return dp2=r+r2;

    }
};
struct SuA{
    St *init, *last;
    SuA(): init(new St(0)), last(init) {}
    inline void extend(char c){
        St *cur=new St(last->len+1, init), *p=last;
        for(;p && !p->next.count(c); p=p->link) p->next[c]=cur;
        if(p){
            St *q=p->next[c];
            if(p->len+1==q->len) cur->link=q;
            else{
                St *clone = new St(p->len+1, q->link);
                clone->next = q->next;
                for(;p && p->next.count(c) && p->next[c]==q; p=p->link)
                    p->next[c] = clone;
                q->link = cur->link = clone;
            }
        }
        last = cur;
    }
    St *go(string s){//run automata
        St *p=init;
        forall(it, s){
            if(!p->next.count(*it)) return NULL;
            p=p->next[*it];
        }
        return p;
    }
    void markterms(){
        for(St *p=last; p; p=p->link) p->terminal=true;
    }
}aut;

char s[100100];

int main() {
	//~ freopen("input.in", "r", stdin);
    ios::sync_with_stdio(0);
    while(scanf("%s", s)>0){
        n=strlen(s);
        aut=SuA();
        forn(i, n) aut.extend(s[i]);
        aut.markterms();//para cantidad de veces
        printf("%I64d\n", aut.init->solve() );
    }

	return 0;
}


#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define dprint(v) cerr << #v"=" << v << endl //;)
#define forr(i,a,b) for(int i=(a); i<(b); i++)
#define forn(i,n) forr(i,0,n)
#define dforn(i,n) for(int i=n-1; i>=0; i--)
#define forall(it,v) for(auto it=v.begin();it!=v.end();++it)
#define sz(c) ((int)c.size())
#define zero(v) memset(v, 0, sizeof(v))
#define pb push_back
#define fst first
#define snd second
typedef long long ll;
typedef pair<int,int> ii;

int n;

struct St {
    int len;
    St *link;
    unordered_map<char,St*> next;
    bool terminal;
    ll dp;
    ll dp2;
    St(int len, St* link=NULL):len(len),link(link), terminal(0), dp(-1), dp2(-1) {}
    inline ll count_paths_to_term(){
        if(dp!=-1) return dp;
        ll &r=dp;
        r=terminal;
        //~ cout << terminal <<  ' ' << sz(next) << endl;
        forall(it, next)
            r+=it->snd->count_paths_to_term();
        return r;
    }

    inline ll solve(bool prim=true){
        ll &r=dp2;
        if(r!=-1) return r;
        r=prim?0:count_paths_to_term();
        //~ dprint(s);
        //~ dprint(r);
        r=r+(r*(r-1))/2;
        //~ dprint(r);
        forall(it, next)
            r+=it->snd->solve(false);
        return r;

    }
};
struct SuA{
    St *init, *last;
    SuA(): init(new St(0)), last(init) {}
    inline void extend(char c){
        St *cur=new St(last->len+1, init), *p=last;
        for(;p && !p->next.count(c); p=p->link) p->next[c]=cur;
        if(p){
            St *q=p->next[c];
            if(p->len+1==q->len) cur->link=q;
            else{
                St *clone = new St(p->len+1, q->link);
                clone->next = q->next;
                for(;p && p->next.count(c) && p->next[c]==q; p=p->link)
                    p->next[c] = clone;
                q->link = cur->link = clone;
            }
        }
        last = cur;
    }
    St *go(string s){//run automata
        St *p=init;
        forall(it, s){
            if(!p->next.count(*it)) return NULL;
            p=p->next[*it];
        }
        return p;
    }
    void markterms(){
        for(St *p=last; p; p=p->link) p->terminal=true;
    }
}aut;

char s[100100];

int main() {
	//~ freopen("input.in", "r", stdin);
    ios::sync_with_stdio(0);
    while(scanf("%s", s)>0){
        n=strlen(s);
        aut=SuA();
        forn(i, n) aut.extend(s[i]);
        aut.markterms();//para cantidad de veces
        printf("%I64d\n", aut.init->solve() );
    }

	return 0;
}


#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)

ll read(){
  ll x=0,f=1;char c=getchar();
  while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
  while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
  return x*f;
}

const int maxn = 100100, maxc = 30;

ll ans;
struct SAM {
	int lst, tot, ch[maxn << 1][maxc], len[maxn << 1], f[maxn << 1], cnt[maxn << 1];
	vector<int> G[maxn << 1];

	void init() {
		lst = tot = 1;
	}
	inline void extend(int c) {
		int p = lst, np = ++tot;
		lst = np; len[np] = len[p] + 1;
		cnt[np]++;
		while (p && !ch[p][c]) {
			ch[p][c] = np;
			p = f[p];
		}
		if (!p) {
			f[np] = 1;
			return;
		}
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {
			f[np] = q;
			return;
		}
		int nq = ++tot;
		len[nq] = len[p] + 1;
		f[nq] = f[q];
		rep(i, 0, maxc - 1) ch[nq][i] = ch[q][i];
		f[q] = f[np] = nq;
		while (p && (ch[p][c] == q)) {
			ch[p][c] = nq;
			p = f[p];
		}
	}
	void ins(char *s) {
		int len = strlen(s + 1);
		rep(i, 1, len) extend(s[i] - 'a');
	}
	ll calc(int x) {
		return x * 1ll * (x + 1) / 2;
	}
	void dfs(int u, int pa) {
		rep(i, 0, G[u].size() - 1) {
			int v = G[u][i];
			dfs(v, u); cnt[u] += cnt[v];
		}
		ans += (len[u] - len[pa]) * 1ll * calc(cnt[u]);
	}
	void solve() {
		rep(i, 1, tot) G[f[i]].pb(i);
		dfs(1, 0);
	}
} sam;
char s[maxn];

void work() {
	scanf("%s", s + 1);
	sam.init();
	sam.ins(s);
	sam.solve();
	printf("%I64d\n", ans);
}

int main() {
  #ifdef LZT
    freopen("in","r",stdin);
  #endif

  work();

  #ifdef LZT
    Debug("My Time: %.3lfms", (double)clock() / CLOCKS_PER_SEC);
  #endif
}


#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<cmath>
#include<iostream>
#include<queue>
#include<string>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<long long,long long> pll;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define rep(i,j,k)  for(register int i=(int)(j);i<=(int)(k);i++)
#define rrep(i,j,k) for(register int i=(int)(j);i>=(int)(k);i--)
#define Debug(...) fprintf(stderr, __VA_ARGS__)

ll read(){
  ll x=0,f=1;char c=getchar();
  while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
  while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
  return x*f;
}

const int maxn = 1000100, maxc = 30;

ll ans;
struct SAM {
	int lst, tot, ch[maxn << 1][maxc], len[maxn << 1], f[maxn << 1], cnt[maxn << 1];
	vector<int> G[maxn];

	void init() {
		lst = tot = 1;
	}
	inline void extend(int c) {
		int p = lst, np = ++tot;
		lst = np; len[np] = len[p] + 1;
		cnt[np]++;
		while (p && !ch[p][c]) {
			ch[p][c] = np;
			p = f[p];
		}
		if (!p) {
			f[np] = 1;
			return;
		}
		int q = ch[p][c];
		if (len[q] == len[p] + 1) {
			f[np] = q;
			return;
		}
		int nq = ++tot;
		len[nq] = len[p] + 1;
		f[nq] = f[q];
		rep(i, 0, maxc - 1) ch[nq][i] = ch[q][i];
		f[q] = f[np] = nq;
		while (p && (ch[p][c] == q)) {
			ch[p][c] = nq;
			p = f[p];
		}
	}
	void ins(char *s) {
		int len = strlen(s + 1);
		rep(i, 1, len) extend(s[i] - 'a');
	}
	ll calc(int x) {
		return x * 1ll * (x + 1) / 2;
	}
	void dfs(int u, int pa) {
		rep(i, 0, G[u].size() - 1) {
			int v = G[u][i];
			dfs(v, u); cnt[u] += cnt[v];
		}
		ans += (len[u] - len[pa]) * 1ll * calc(cnt[u]);
	}
	void solve() {
		rep(i, 1, tot) G[f[i]].pb(i);
		dfs(1, 0);
	}
} sam;
char s[maxn];

void work() {
	scanf("%s", s + 1);
	sam.init();
	sam.ins(s);
	sam.solve();
	printf("%I64d\n", ans);
}

int main() {
  #ifdef LZT
    freopen("in","r",stdin);
  #endif

  work();

  #ifdef LZT
    Debug("My Time: %.3lfms", (double)clock() / CLOCKS_PER_SEC);
  #endif
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

typedef pair<long long,long long> PLL;
const int N=1e5+5;
int n,m;
int tax[N],rk[N],tp[N],sa[N],height[N];
string s;
stack<PLL>stk;

bool cmp(int* r, int a, int b, int k) {
    return r[a] == r[b] && r[a + k] == r[b + k];
}

void radix_sort()
{
    for (int i = 0; i <= m; i++) tax[i] = 0;
    for (int i = 1; i <= n; i++) tax[rk[tp[i]]]++;
    for (int i = 1; i <= m; i++) tax[i] += tax[i - 1];
    for (int i = n; i >= 1; i--) sa[tax[rk[tp[i]]]--] = tp[i];
}

void get_sa()
{
    for (int i = 1; i <= n; i++)
	{
        rk[i] = s[i];
        tp[i] = i;
        m = max(m, (int)s[i]);
    }
    radix_sort();
    for (int j = 1, p = 0; p < n; j <<= 1, m = p)
	{
        p = 0;
        for (int i = n - j + 1; i <= n; i++) tp[++p] = i;
        for (int i = 1; i <= n; i++)
		{
            if (sa[i] > j) tp[++p] = sa[i] - j;
        }
        radix_sort();
        swap(rk, tp);
        rk[sa[1]] = p = 1;
        for (int i = 2; i <= n; i++)
		{
            rk[sa[i]] = cmp(tp, sa[i], sa[i - 1], j) ? p : ++p;
        }
    }
}

void get_height()
{
	for (int i = 1, k = 0; i <= n; ++i)
	{
  		if (k) --k;
  		while (s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
  		height[rk[i]] = k;
	}
}

int main()
{
	cin>>s;
	n=s.size();
	s="#"+s;
	get_sa();
	get_height();

	long long cnt=0;
	long long ans=1ll*n*(n+1)/2;

	for(int i=n;i>=2;i--)
	{
		PLL t={height[i],1};
		while(stk.size()&&stk.top().first>t.first)
		{
			cnt-=stk.top().first*stk.top().second;
			t.second+=stk.top().second;
			stk.pop();
		}
		cnt+=t.first*t.second;
		stk.push(t);

		ans+=cnt;
	}
	cout<<ans<<endl;
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

typedef pair<long long,long long> PLL;
const int N=1e5+5;
int n,m;
int tax[N],rk[N],tp[N],sa[N],height[N];
string s;
stack<PLL>stk;

bool cmp(int* r, int a, int b, int k) {
    return r[a] == r[b] && r[a + k] == r[b + k];
}

void radix_sort()
{
    for (int i = 0; i <= m; i++) tax[i] = 0;
    for (int i = 1; i <= n; i++) tax[rk[tp[i]]]++;
    for (int i = 1; i <= m; i++) tax[i] += tax[i - 1];
    for (int i = n; i >= 1; i--) sa[tax[rk[tp[i]]]--] = tp[i];
}

void get_sa()
{
    for (int i = 1; i <= n; i++)
	{
        rk[i] = s[i];
        tp[i] = i;
        m = max(m, (int)s[i]);
    }
    radix_sort();
    for (int j = 1, p = 0; p < n; j <<= 1, m = p)
	{
        p = 0;
        for (int i = n - j + 1; i <= n; i++) tp[++p] = i;
        for (int i = 1; i <= n; i++)
		{
            if (sa[i] > j) tp[++p] = sa[i] - j;
        }
        radix_sort();
        swap(rk, tp);
        rk[sa[1]] = p = 1;
        for (int i = 2; i <= n; i++)
		{
            rk[sa[i]] = cmp(tp, sa[i], sa[i - 1], j) ? p : ++p;
        }
    }
}

void get_height()
{
	for (int i = 1, k = 0; i <= n; ++i)
	{
  		if (k) --k;
  		while (s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
  		height[rk[i]] = k;
	}
}

int main()
{
	cin>>s;
	n=s.size();
	s="#"+s;
	get_sa();
	get_height();

	long long cnt=0;
	long long ans=n*(n+1)/2;

	for(int i=n;i>=2;i--)
	{
		PLL t={height[i],1};
		while(stk.size()&&stk.top().first>t.first)
		{
			cnt-=stk.top().first*stk.top().second;
			t.second+=stk.top().second;
			stk.pop();
		}
		cnt+=t.first*t.second;
		stk.push(t);

		ans+=cnt;
	}
	cout<<ans<<endl;
	return 0;
}


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

#define si(a) scanf("%d",&a)
#define f first
#define s second
#define mp(a,b) make_pair(a,b)
#define MAX 100010
#define MAX_lg 20
#define minchar 'a'
#define Index(a) (((a) < len) ? index[mlgn][a] : -1)
int Count[MAX], output[MAX];
int pos[MAX], index[MAX_lg][MAX], lcp[MAX], len, mlgn;
struct suffixArray
{

    suffixArray() {}
    suffixArray(const char *S)
    {
        create(S);
    }
    void CountSort(int add)
    {
        int to = max(len, 26);
        memset(Count, 0, sizeof(Count));
        for(int i = 0; i < len; i++) ++Count[ Index(pos[i] + add) + 1 ];
        for(int i = 1; i <= to; i++) Count[i] += Count[i-1];
        for(int i = len-1; i >= 0; i--) output[ --Count[ Index(pos[i] + add) + 1 ] ] = pos[i];
        for(int i = 0; i < len; i++) pos[i] = output[i];
    }
    int Lcp(int x, int y)
    {
        int ret = 0;
        for(int i = mlgn; i >= 0 && x < len && y < len; i--) if(index[i][x] == index[i][y])
                x += (1 << i),
                     y += (1 << i),
                          ret += (1 << i);
        return ret;
    }
    void create(const char *S)
    {
        len = strlen(S), mlgn = 0;
        for(int i = 0; i < len; i++) index[0][i] = S[i] - minchar;
        for(int done = 1; done < len; done <<= 1)
        {
            for(int i = 0; i < len; i++) pos[i] = i;
            CountSort(done);
            CountSort(0);
            for(int i = 0; i < len; i++)
            {
                int sc1 = (i > 0) ? Index(pos[i-1] + done) : -1;
                int sc2 = Index(pos[i] + done);
                index[mlgn+1][pos[i]] = (i > 0 && index[mlgn][pos[i]] == index[mlgn][pos[i-1]] && sc1 == sc2) ? index[mlgn+1][pos[i-1]] : i;
            }
            mlgn++;
        }
        lcp[0] = 0;
        for(int i = 1; i < len; i++) lcp[i] = Lcp(pos[i], pos[i-1]);
    }
};

char str[MAX];

int main()
{
    //freopen("input.txt","r",stdin);
    scanf("%s",str);
    suffixArray ob(str);
    long long ans=len-pos[0],ttt=ans;
    stack<pair<int,int> > st;
    st.push(mp(st,1));
    for(int i=1;i<len;i++){
        int cnt=0;
        while(!st.empty()){
            pair<int,int> now=st.top();
            if(now.f<=lcp[i])break;
            cnt+=now.s;
            st.pop();
            ttt-=(long long)now.f*now.s;
        }
        st.push(mp(lcp[i],cnt));
        ttt+=(long long)cnt*lcp[i];
        ttt+=(len-pos[i]);
        st.push(mp(len-pos[i],1));
        ans+=ttt;
    }
    cout<<ans<<endl;
    return 0;
}


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

#define si(a) scanf("%d",&a)
#define f first
#define s second
#define mp(a,b) make_pair(a,b)
#define MAX 100010
#define MAX_lg 20
#define minchar 'a'
#define Index(a) (((a) < len) ? index[mlgn][a] : -1)
int Count[MAX], output[MAX];
int pos[MAX], index[MAX_lg][MAX], lcp[MAX], len, mlgn;
struct suffixArray
{

    suffixArray() {}
    suffixArray(const char *S)
    {
        create(S);
    }
    void CountSort(int add)
    {
        int to = max(len, 26);
        memset(Count, 0, sizeof(Count));
        for(int i = 0; i < len; i++) ++Count[ Index(pos[i] + add) + 1 ];
        for(int i = 1; i <= to; i++) Count[i] += Count[i-1];
        for(int i = len-1; i >= 0; i--) output[ --Count[ Index(pos[i] + add) + 1 ] ] = pos[i];
        for(int i = 0; i < len; i++) pos[i] = output[i];
    }
    int Lcp(int x, int y)
    {
        int ret = 0;
        for(int i = mlgn; i >= 0 && x < len && y < len; i--) if(index[i][x] == index[i][y])
                x += (1 << i),
                     y += (1 << i),
                          ret += (1 << i);
        return ret;
    }
    void create(const char *S)
    {
        len = strlen(S), mlgn = 0;
        for(int i = 0; i < len; i++) index[0][i] = S[i] - minchar;
        for(int done = 1; done < len; done <<= 1)
        {
            for(int i = 0; i < len; i++) pos[i] = i;
            CountSort(done);
            CountSort(0);
            for(int i = 0; i < len; i++)
            {
                int sc1 = (i > 0) ? Index(pos[i-1] + done) : -1;
                int sc2 = Index(pos[i] + done);
                index[mlgn+1][pos[i]] = (i > 0 && index[mlgn][pos[i]] == index[mlgn][pos[i-1]] && sc1 == sc2) ? index[mlgn+1][pos[i-1]] : i;
            }
            mlgn++;
        }
        lcp[0] = 0;
        for(int i = 1; i < len; i++) lcp[i] = Lcp(pos[i], pos[i-1]);
    }
};

char str[MAX];

int main()
{
    //freopen("input.txt","r",stdin);
    scanf("%s",str);
    suffixArray ob(str);
    long long ans=len-pos[0],ttt=ans;
    stack<pair<int,int> > st;
    st.push(mp(len-pos[0],1));
    for(int i=1;i<len;i++){
        int cnt=0;
        while(!st.empty()){
            pair<int,int> now=st.top();
            if(now.f<=lcp[i])break;
            cnt+=now.s;
            st.pop();
            ttt-=(long long)now.f*now.s;
        }
        st.push(mp(lcp[i],cnt));
        ttt+=(long long)cnt*lcp[i];
        ttt+=(len-pos[i]);
        st.push(mp(len-pos[i],1));
        ans+=ttt;
    }
    cout<<ans<<endl;
    return 0;
}