#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int doubles, lengths, dat[100002], tmp[100002], rank_[100002];
bool compare_suffix(int i, int j) {
if (dat[i] == dat[j]) {
int ri = (i + doubles <= lengths ? dat[i + doubles] : -1);
int rj = (j + doubles <= lengths ? dat[j + doubles] : -1);
return ri < rj;
}
return dat[i] < dat[j];
}
vector<int> suffix_array(string S) {
lengths = S.size();
vector<int> arrays(lengths + 1);
for (int i = 0; i <= lengths; i++) {
arrays[i] = i;
dat[i] = i < lengths ? S[i] : -1;
}
for (doubles = 1; doubles <= lengths; doubles <<= 1) {
sort(arrays.begin(), arrays.begin() + lengths + 1, compare_suffix);
tmp[arrays[0]] = 0;
for (int i = 1; i <= lengths; i++) tmp[arrays[i]] = tmp[arrays[i - 1]] + (compare_suffix(arrays[i - 1], arrays[i]) ? 1 : 0);
for (int i = 0; i <= lengths; i++) dat[i] = tmp[i];
}
return arrays;
}
vector<int> lcp(string s, vector<int> sa) {
vector<int> ret; ret.resize(lengths + 1);
for (int i = 0; i <= lengths; i++) rank_[sa[i]] = i;
int h = 0; ret[0] = 0;
for (int i = 0; i < lengths; i++) {
int j = sa[rank_[i] - 1];
if (h > 0) h--;
for (; j + h < lengths && i + h < lengths; h++) {
if (s[j + h] != s[i + h]) break;
}
ret[rank_[i] - 1] = h;
}
return ret;
}
string s, f; long long ret = 0;
int main() {
cin >> s;
vector<int> v1 = suffix_array(s);
vector<int> v2 = lcp(s, v1);
for (int i = 1; i <= s.size(); i++) {
ret += 1LL * (lengths - v1[i]) * (lengths - v1[i] + 1) / 2 - 1LL * v2[i] * (v2[i] + 1) / 2;
}
cout << ret << endl;
return 0;
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YWxnb3JpdGhtPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwppbnQgZG91YmxlcywgbGVuZ3RocywgZGF0WzEwMDAwMl0sIHRtcFsxMDAwMDJdLCByYW5rX1sxMDAwMDJdOwpib29sIGNvbXBhcmVfc3VmZml4KGludCBpLCBpbnQgaikgewoJaWYgKGRhdFtpXSA9PSBkYXRbal0pIHsKCQlpbnQgcmkgPSAoaSArIGRvdWJsZXMgPD0gbGVuZ3RocyA/IGRhdFtpICsgZG91Ymxlc10gOiAtMSk7CgkJaW50IHJqID0gKGogKyBkb3VibGVzIDw9IGxlbmd0aHMgPyBkYXRbaiArIGRvdWJsZXNdIDogLTEpOwoJCXJldHVybiByaSA8IHJqOwoJfQoJcmV0dXJuIGRhdFtpXSA8IGRhdFtqXTsKfQp2ZWN0b3I8aW50PiBzdWZmaXhfYXJyYXkoc3RyaW5nIFMpIHsKCWxlbmd0aHMgPSBTLnNpemUoKTsKCXZlY3RvcjxpbnQ+IGFycmF5cyhsZW5ndGhzICsgMSk7Cglmb3IgKGludCBpID0gMDsgaSA8PSBsZW5ndGhzOyBpKyspIHsKCQlhcnJheXNbaV0gPSBpOwoJCWRhdFtpXSA9IGkgPCBsZW5ndGhzID8gU1tpXSA6IC0xOwoJfQoJZm9yIChkb3VibGVzID0gMTsgZG91YmxlcyA8PSBsZW5ndGhzOyBkb3VibGVzIDw8PSAxKSB7CgkJc29ydChhcnJheXMuYmVnaW4oKSwgYXJyYXlzLmJlZ2luKCkgKyBsZW5ndGhzICsgMSwgY29tcGFyZV9zdWZmaXgpOwoJCXRtcFthcnJheXNbMF1dID0gMDsKCQlmb3IgKGludCBpID0gMTsgaSA8PSBsZW5ndGhzOyBpKyspIHRtcFthcnJheXNbaV1dID0gdG1wW2FycmF5c1tpIC0gMV1dICsgKGNvbXBhcmVfc3VmZml4KGFycmF5c1tpIC0gMV0sIGFycmF5c1tpXSkgPyAxIDogMCk7CgkJZm9yIChpbnQgaSA9IDA7IGkgPD0gbGVuZ3RoczsgaSsrKSBkYXRbaV0gPSB0bXBbaV07Cgl9CglyZXR1cm4gYXJyYXlzOwp9CnZlY3RvcjxpbnQ+IGxjcChzdHJpbmcgcywgdmVjdG9yPGludD4gc2EpIHsKCXZlY3RvcjxpbnQ+IHJldDsgcmV0LnJlc2l6ZShsZW5ndGhzICsgMSk7Cglmb3IgKGludCBpID0gMDsgaSA8PSBsZW5ndGhzOyBpKyspIHJhbmtfW3NhW2ldXSA9IGk7CglpbnQgaCA9IDA7IHJldFswXSA9IDA7Cglmb3IgKGludCBpID0gMDsgaSA8IGxlbmd0aHM7IGkrKykgewoJCWludCBqID0gc2FbcmFua19baV0gLSAxXTsKCQlpZiAoaCA+IDApIGgtLTsKCQlmb3IgKDsgaiArIGggPCBsZW5ndGhzICYmIGkgKyBoIDwgbGVuZ3RoczsgaCsrKSB7CgkJCWlmIChzW2ogKyBoXSAhPSBzW2kgKyBoXSkgYnJlYWs7CgkJfQoJCXJldFtyYW5rX1tpXSAtIDFdID0gaDsKCX0KCXJldHVybiByZXQ7Cn0Kc3RyaW5nIHMsIGY7IGxvbmcgbG9uZyByZXQgPSAwOwppbnQgbWFpbigpIHsKCWNpbiA+PiBzOwoJdmVjdG9yPGludD4gdjEgPSBzdWZmaXhfYXJyYXkocyk7Cgl2ZWN0b3I8aW50PiB2MiA9IGxjcChzLCB2MSk7Cglmb3IgKGludCBpID0gMTsgaSA8PSBzLnNpemUoKTsgaSsrKSB7CgkJcmV0ICs9IDFMTCAqIChsZW5ndGhzIC0gdjFbaV0pICogKGxlbmd0aHMgLSB2MVtpXSArIDEpIC8gMiAtIDFMTCAqIHYyW2ldICogKHYyW2ldICsgMSkgLyAyOwoJfQoJY291dCA8PCByZXQgPDwgZW5kbDsKCXJldHVybiAwOwp9Cg==