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 Kotlin (1.3.71) (judge verdict: Accepted)

import kotlin.math.max


fun main() {

    fun calcLCP(t: String, suffixArray: List<Int>): IntArray {
        val s = "${t}$"
        val n = s.length
        val lcp = IntArray(n - 1)
        val positions = IntArray(n)
        suffixArray.forEachIndexed { index, suff ->
            positions[suff] = index
        }

        var k = 0
        for (i in 0 until n - 1) {
            val position = positions[i]
            val j = suffixArray[position - 1]
            while (s[i + k] == s[j + k]) k++
            lcp[position - 1] = k
            k = max(k - 1, 0)
        }

        return lcp
    }

    fun suffixArray(inputString: String): List<Int> {
        val s = "$inputString$"
        val n = s.length
        var p: IntArray // Ordering of the strings
        val c = IntArray(n) { -1 } // Equivalence classes

        // k = 0
        val charPosition = s.mapIndexed { index, ch -> Pair(ch, index) }.sortedBy { it.first }

        p = charPosition.map { it.second }.toIntArray()

        charPosition.forEachIndexed { index, pair ->
            when {
                index == 0 -> c[p[index]] = 0
                pair.first == charPosition[index - 1].first -> c[p[index]] = c[p[index - 1]]
                else -> c[p[index]] = c[p[index - 1]] + 1
            }
        }

        fun countSort(ordering: IntArray, classes: IntArray): IntArray {
            val newOrdering = IntArray(n)
            val counts = IntArray(n)
            classes.forEach { `class` -> counts[`class`]++ }

            val position = IntArray(n)
            for (i in 1 until n) position[i] = position[i - 1] + counts[i - 1]

            ordering.forEach { index ->
                val `class` = classes[index]
                newOrdering[position[`class`]] = index
                position[`class`]++
            }
            return newOrdering
        }

        var k = 0
        while (1 shl k < n) {
            // k -> k + 1

            for (i in p.indices) p[i] = (p[i] - (1 shl k) + n) % n

            p = countSort(p, c)
            val cNew = IntArray(n)
            cNew[p[0]] = 0
            for (i in 1 until n) {
                val prev = Pair(c[p[i - 1]], c[(p[i - 1] + (1 shl k)) % n])
                val curr = Pair(c[p[i]], c[(p[i] + (1 shl k)) % n])
                cNew[p[i]] = if (prev == curr) cNew[p[i - 1]] else cNew[p[i - 1]] + 1
            }
            cNew.forEachIndexed { index, `class` -> c[index] = `class` }
            k++
        }

        return p.toList()
    }

    fun numberOfDifferentSubstrings(t: String): Long {
        val tSuffix = suffixArray(t)
        val lcp = calcLCP(t, tSuffix)
        var ans = 0L
        for (i in 1 until tSuffix.size) {
            ans += t.length - tSuffix[i] - lcp[i - 1]
        }

        return ans
    }

    val s = readLn()
    println(numberOfDifferentSubstrings(s))
}

// Input Reader
private fun readLn() = readLine()!!