#include <bits/stdc++.h>   using namespace std;   const int mod = 998244353;   const int inf = 1 << 30;   const int maxn = 100000 + 5;   int tot, dfn[maxn << 1], ord[maxn << 1];   namespace hld {   const int maxn = ::maxn << 1;   struct edge {     int to, nxt;   } g[maxn];   int head[maxn], ecnt = 0;   void add(int x, int y) {     g[++ecnt] = {y, head[x]};     head[x] = ecnt;   }   int siz[maxn], dep[maxn], fa[maxn], son[maxn], top[maxn];   void dfs(int p, int d, int old) {     dfn[p] = ++tot;     ord[tot] = p;     dep[p] = d;     fa[p] = old;     siz[p] = 1;     int m = -1;     for (int i = head[p]; i; i = g[i].nxt) {       int v = g[i].to;       if (v == fa[p]) continue;       dfs(v, d + 1, p);       siz[p] += siz[v];       if (siz[v] > m) son[p] = v, m = siz[v];     }   }   void dfs(int p, int tp) {     top[p] = tp;     if (!son[p]) return;     dfs(son[p], tp);     for (int i = head[p]; i; i = g[i].nxt) {       int v = g[i].to;       if (v == fa[p] || v == son[p]) continue;       dfs(v, v);     }   }   void build(int rt = 1) {     memset(son, 0, sizeof(son));     dfs(rt, rt, 0);     dfs(rt, rt);   }   int qlca(int x, int y) {     while (top[x] != top[y]) {       if (dep[top[x]] < dep[top[y]]) swap(x, y);       x = fa[top[x]];     }     if (dep[x] > dep[y]) swap(x, y);     return x;   }   }  // namespace hld   vector<int> edge[maxn << 1];   struct sam {     int sz, last, cnt[maxn << 1];     int len[maxn << 1], link[maxn << 1], ch[maxn << 1][26];     void clear() {       for (int i = 1; i <= sz; i++) {         len[i] = link[i] = cnt[i] = 0;         memset(ch[i], 0, sizeof(ch[i]));       }       sz = last = 1;     }     sam() { clear(); }     int insert(int c) {       int cur = ++sz, p = last;       len[cur] = len[last] + 1;       cnt[cur] = 1;       for (; p && !ch[p][c]; p = link[p]) ch[p][c] = cur;       if (!p)         link[cur] = 1;       else {         int q = ch[p][c];         if (len[p] + 1 == len[q])           link[cur] = q;         else {           int nq = ++sz;           len[nq] = len[p] + 1;           link[nq] = link[q];           link[q] = link[cur] = nq;           memcpy(ch[nq], ch[q], sizeof ch[q]);           for (; ch[p][c] == q; p = link[p]) ch[p][c] = nq;         }       }       return last = cur;     }     void build(int tp) {       if (tp == 0) {         for (int i = 1; i <= sz; i++) {           len[i]++;           edge[link[i]].push_back(i);         }       } else {         for (int i = 1; i <= sz; i++) {           len[i]++;           hld::add(link[i], i);         }         hld::build();       }     }   } ta, tb;   int n;   long long ans;   char s[maxn];   int prepos[maxn], sufpos[maxn];   set<int> bag[maxn << 1];   long long val[maxn << 1];   void add(int u, int p) {     auto it = bag[u].lower_bound(p);     int node = -1, d = hld::dep[ord[p]];     if (it != bag[u].end()) {       node = hld::qlca(ord[p], ord[*it]);     }     if (it != bag[u].begin()) {       it--;       int y = hld::qlca(ord[p], ord[*it]);       if (node == -1 || abs(hld::dep[node] - d) > abs(hld::dep[y] - d)) node = y;     }     val[u] += tb.len[ord[p]];     if (node != -1) val[u] -= tb.len[node];     bag[u].insert(p);   }   void dfs(int u) {     for (int v : edge[u]) {       dfs(v);       if (bag[v].size() > bag[u].size()) {         swap(bag[u], bag[v]);         val[u] = val[v];       }       for (auto& x : bag[v]) add(u, x);     }     ans += (val[u] + 1) * (ta.len[u] - ta.len[ta.link[u]]);     ;   }   int main() {     scanf( %s , s + 1);     n = strlen(s + 1);     prepos[0] = sufpos[n + 1] = 1;     for (int i = 1; i <= n; i++) {       prepos[i] = ta.insert(s[i] -  a );     }     for (int i = n; i >= 1; i--) {       sufpos[i] = tb.insert(s[i] -  a );     }     ta.build(0);     tb.build(1);     for (int i = 0; i < n; i++) {       add(prepos[i], dfn[sufpos[i + 2]]);     }     dfs(1);     cout << ans << endl;     return 0;   }