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

namespace str {

template<class C>
vector<int> z_algorithm(const C &s) {
	int n = int(s.size());
	if(!n) return {};
	vector<int> Z(n);
	Z[0] = n;
	int i = 1, j = 0;
	while(i < n) {
		while(i+j < n and s[j] == s[i+j]) j++;
		Z[i] = j;
		if(!j) {
			i++;
			continue;
		}
		int k = 1;
		while(k < j and k+Z[k] < j) {
			Z[i+k] = Z[k];
			k++;
		}
		i += k;
		j -= k;
	}
	return Z;
}

vector<int> SA_naive(const vector<int> &s) {
	int n = int(s.size());
	vector<int> sa(n);
	iota(sa.begin(), sa.end(), 0);
	sort(sa.begin(), sa.end(), [&](int l, int r)->bool {
		if(l == r) return false;
		while(l < n and r < n) {
			if(s[l] != s[r]) return s[l] < s[r];
			l++; r++;
		}
		return l == n;
	});
	return sa;
}

vector<int> SA_ant(vector<int> rnk) {
	int n = int(rnk.size());
	vector<int> sa(n), tmp(n);
	iota(sa.begin(), sa.end(), 0);
	for(int k = 1; k < n; k <<= 1) {
		auto cmp = [&](int x, int y)->bool {
			if(rnk[x] != rnk[y]) return rnk[x] < rnk[y];
			int rx = x+k < n ? rnk[x+k]:-1;
			int ry = y+k < n ? rnk[y+k]:-1;
			return rx < ry;
		};
		sort(sa.begin(), sa.end(), cmp);
		tmp[sa[0]] = 0;
		for(int i = 1; i < n; i++) {
			tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1], sa[i]) ? 1:0);
		}
		swap(tmp, rnk);
	}
	return sa;
}

template<int TS_NAIVE = 10, int TS_ANT = 40>
vector<int> SA_IS(const vector<int> &s, int upper) {
	int n = int(s.size());
	if(!n) return {};
	if(n == 1) return {0};
	if(n == 2) {
		if(s[0] < s[1]) return {0, 1};
		else return {1, 0};
	}
	if(n < TS_NAIVE) return SA_naive(s);
	if(n < TS_ANT) return SA_ant(s);
	vector<int> sa(n);
	vector<bool> ls(n);
	for(int i = n-2; i >= 0; i--) {
		ls[i] = (s[i] == s[i+1]) ? ls[i+1]:(s[i]<s[i+1]);
	}
	vector<int> sum_l(upper+1), sum_s(upper+1);
	for(int i = 0; i < n; i++) {
		if(!ls[i]) sum_s[s[i]]++;
		else sum_l[s[i]+1]++;
	}
	for(int i = 0; i <= upper; i++) {
		sum_s[i] += sum_l[i];
		if(i < upper) sum_l[i+1] += sum_s[i];
	}
	auto induce_sort = [&](const vector<int> &lms)->void {
		fill(sa.begin(), sa.end(), -1);
		vector<int> buf(upper+1);
		copy(sum_s.begin(), sum_s.end(), buf.begin());
		for(int d:lms) {
			if(d == n) continue;
			sa[buf[s[d]]++] = d;
		}
		copy(sum_l.begin(), sum_l.end(), buf.begin());
		sa[buf[s[n-1]]++] = n-1;
		for(int i = 0; i < n; i++) {
			int v = sa[i];
			if(v >= 1 and !ls[v-1]) {
				sa[buf[s[v-1]]++] = v-1;
			}
		}
		copy(sum_l.begin(), sum_l.end(), buf.begin());
		for(int i = n-1; i >= 0; i--) {
			int v = sa[i];
			if(v >= 1 and ls[v-1]) {
				sa[--buf[s[v-1]+1]] = v-1;
			}
		}
	};
	vector<int> lms_map(n+1, -1);
	int m = 0;
	for(int i = 1; i < n; i++) {
		if(!ls[i-1] and ls[i]) {
			lms_map[i] = m++;
		}
	}
	vector<int> lms;
	lms.reserve(m);
	for(int i = 1; i < n; i++) {
		if(!ls[i-1] and ls[i]) {
			lms.push_back(i);
		}
	}
	induce_sort(lms);
	if(m) {
		vector<int> sorted_lms;
		sorted_lms.reserve(m);
		for(int v:sa) {
			if(lms_map[v] != -1) sorted_lms.push_back(v);
		}
		vector<int> rec_s(m);
		int rec_upper = 0;
		rec_s[lms_map[sorted_lms[0]]] = 0;
		for(int i = 1; i < m; i++) {
			int l = sorted_lms[i-1], r = sorted_lms[i];
			int end_l = (lms_map[l]+1 < m) ? lms[lms_map[l]+1]:n;
			int end_r = (lms_map[r]+1 < m) ? lms[lms_map[r]+1]:n;
			bool same = (end_l-l == end_r-r);
			if(same) {
				while(l < end_l) {
					if(s[l] != s[r]) break;
					l++; r++;
				}
				if(l == n or s[l] != s[r]) same = false;
			}
			if(!same) rec_upper++;
			rec_s[lms_map[sorted_lms[i]]] = rec_upper;
		}
		vector<int> rec_sa = SA_IS<TS_NAIVE, TS_ANT>(rec_s, rec_upper);
		for(int i = 0; i < m; i++) {
			sorted_lms[i] = lms[rec_sa[i]];
		}
		induce_sort(sorted_lms);
	}
	return sa;
}

vector<int> suffix_array(const vector<int> &s, int upper) {return SA_IS(s, upper);}

template<class T>
vector<int> suffix_array(const vector<T> &s) {
	int n = int(s.size());
	vector<int> idx(n);
	iota(idx.begin(), idx.end(), 0);
	sort(idx.begin(), idx.end(), [&](int l, int r)->int {return s[l] < s[r];});
	vector<int> s2(n);
	int now = 0;
	for(int i = 0; i < n; i++) {
		if(i and s[idx[i-1]] != s[idx[i]]) now++;
		s2[idx[i]] = now;
	}
	return SA_IS(s2, now);
}

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

template<class T>
vector<int> lcp_array(const vector<T> &s, vector<int> &sa) {
	int n = int(s.size());
	assert(n);
	vector<int> rnk(n);
	for(int i = 0; i < n; i++) {
		rnk[sa[i]] = i;
	}
	vector<int> lcp(n-1);
	int h = 0;
	for(int i = 0; i < n; i++) {
		if(h) h--;
		if(rnk[i] == 0) continue;
		int j = sa[rnk[i]-1];
		for(; j+h < n and i+h < n; h++) {
			if(s[i+h] != s[j+h]) break;
		}
		lcp[rnk[i]-1] = h;
	}
	return lcp;
}

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

//maybe more...
//Aho-Corasick法
//Manacher's Algorithm
//KMP法

//vector<int> z_algorithm(C&) ##string or vector<integer_type>
//vector<int> suffix_array(vector<int>&, upper)
//vector<int> suffix_array(vector<T>&)
//vector<int> suffix_array(string&)
//vector<int> lcp_array(vector<T>&, SA&)
//vector<int> lcp_array(string&, SA&)

} // namespace str

int main() {
  string s;
  cin >> s;
  auto sa = str::suffix_array(s);
  auto lcp = str::lcp_array(s, sa);
  int n = s.size();
  cout << int64_t(n)*(n+1)/2 - accumulate(lcp.begin(), lcp.end(), 0LL) << endl;
}

Measured memory_bytes: 15620