Problem:
Score : 100 points

Problem Statement

You are given a string of length N. Calculate the number of distinct substrings of S.

Constraints

1 \leq N \leq 500,000

S consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

S

Output

Print the answer.

Sample Input 1

abcbcba

Sample Output 1

21

Sample Input 2

mississippi

Sample Output 2

53

Sample Input 3

ababacaca

Sample Output 3

33

Sample Input 4

aaaaa

Sample Output 4

5

Solution in PyPy3 (7.3.0) (judge verdict: Time Limit Exceeded)

class SuffixArray:
    def __init__(self, S):
        self.N = len(S)
        self.S = S
        self.sa = self.__make_sa()
        self.lcp, self.rank = self.__make_lcp()

    @staticmethod
    def atoi(a):
        return ord(a) - ord("a") + 1

    def show(self):
        for i in range(self.N + 1):
            print(i, self.sa[i], self.lcp[i], self.S[self.sa[i]:])

    def __make_sa(self):
        """配列（文字列）Sのsuffix arrayを返す O(N(logN)^2)"""
        N = self.N
        SA = list(range(N + 1))
        rank = [-1] * (N + 1)
        tmp = [0] * (N + 1)
        k = 1

        for i, s in enumerate(self.S):
            rank[i] = self.atoi(s)

        def key(i):
            if i + k <= N:
                return (rank[i], rank[i + k])
            return (rank[i], -1)

        def cmp(i, j):
            return key(i) < key(j)

        while k <= N:
            SA.sort(key=key)
            tmp[SA[0]] = 0
            for i in range(1, N + 1):
                tmp[SA[i]] = tmp[SA[i - 1]] + cmp(SA[i - 1], SA[i])
            for i in range(N + 1):
                rank[i] = tmp[i]
            k *= 2
        return SA

    def __make_lcp(self):
        lcp = [0] * (self.N + 1)
        rank = [0] * (self.N + 1)
        for i in range(self.N + 1):
            rank[self.sa[i]] = i
        h = 0
        for i in range(self.N):
            j = self.sa[rank[i] - 1]
            if h > 0:
                h -= 1
            while j + h < self.N and i + h < self.N:
                if self.S[i + h] != self.S[j + h]:
                    break
                h += 1
            lcp[rank[i] - 1] = h
        return lcp, rank

    def contain(self, T, side="left"):
        """文字列SにTが含まれているかを返すO(|T|log|S|)
        input
            T: 検索する文字列（配列）
            side: left　-> S[sa[i]:sa[i]+NT] == Tとなる最小のindex iを返す
                  right -> 最大のindexを返す
        output:
            含まれる場合: S[sa[i]: sa[i]+NT] == Tとなる最小or最大のi
            含まれない場合: -1
        """
        NT = len(T)
        if NT > self.N:
            return -1
        L = 0
        R = self.N
        if side == "left":
            while R - L > 1:
                m = (L + R) // 2
                i = self.sa[m]
                if self.S[i:i + NT] < T:
                    L = m
                else:
                    R = m
            i = self.sa[R]
            if self.S[i:i + NT] == T:
                return R
        else:
            R += 1
            while R - L > 1:
                m = (L + R) // 2
                i = self.sa[m]
                if self.S[i:i + NT] <= T:
                    L = m
                else:
                    R = m
            i = self.sa[L]
            if self.S[i:i + NT] == T:
                return L
        return -1

    def get_indices(self, T):
        """Sの中に含まれるTの位置を格納したindexのリストを返す"""
        L = self.contain(T, side="left")
        if L == -1:
            return []
        R = self.contain(T, side="right")
        return [self.sa[i] for i in range(L, R+1)]


S = input()
N = len(S)
SA = SuffixArray(S)

ans = 0
for x, y in zip(SA.sa[1:], SA.lcp):
    ans += N - x - y

print(ans)