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 Ruby (2.7.1) (judge verdict: Accepted)

# frozen_string_literal: true

# induce sort (internal routine)
def sa_is_induce(s, ls, sum_l, sum_s, lms)
  n = s.size
  sa = [-1]*n

  buf = *sum_s # deep copy
  lms.each{ |lms|
    if lms != n then
      sa[buf[s[lms]]] = lms
      buf[s[lms]] += 1
    end
  }

  buf = *sum_l # deep copy
  sa[buf[s[-1]]] = n-1
  buf[s[-1]] += 1
  sa.each{ |v|
    if v>=1 && !ls[v-1] then
      sa[buf[s[v-1]]] = v-1
      buf[s[v-1]] += 1
    end
  }

  buf = *sum_l # deep copy
  sa.reverse_each{ |v|
    if v>=1 && ls[v-1] then
      buf[s[v-1]+1] -= 1
      sa[buf[s[v-1]+1]] = v-1
    end
  }

  return sa
end

# SA-IS (internal routine)
def sa_is(s, upper)
  n = s.size

  return [] if n == 0
  return [0] if n == 1

  ls = [false]*n
  (n-2).downto(0){ |i|
    ls[i] = s[i]==s[i+1] ? ls[i+1] : s[i]<s[i+1]
  }

  sum_l = [0]*(upper+1)
  sum_s = [0]*(upper+1)
  n.times{ |i|
    if ls[i] then
      sum_l[s[i]+1] += 1
    else
      sum_s[s[i]] += 1
    end
  }
  0.upto(upper){ |i|
    sum_s[i] += sum_l[i]
    sum_l[i+1] += sum_s[i] if i<upper
  }

  lms = (1 ... n).select{ |i| !ls[i-1] && ls[i] }
  m=lms.size
  lms_map = [-1]*(n+1)
  lms.each_with_index{ |lms, id| lms_map[lms] = id }

  sa = sa_is_induce(s, ls, sum_l, sum_s, lms)

  return sa if m == 0

  sorted_lms = sa.select{ |sa| lms_map[sa] != -1 }
  rec_s = [0]*m
  rec_upper = 0
  rec_s[lms_map[sorted_lms[0]]] = 0
  1.upto(m-1){ |i|
    l, r = sorted_lms[i-1, 2]
    end_l = lms[lms_map[l]+1]||n
    end_r = lms[lms_map[r]+1]||n
    same = true
    if end_l-l != end_r-r then
      same = false
    else
      while l < end_l do
        break if s[l] != s[r]
        l+=1
        r+=1
      end
      same = false if l==n || s[l]!=s[r]
    end
    rec_upper += 1 if not same
    rec_s[lms_map[sorted_lms[i]]] = rec_upper
  }

  sa_is(rec_s, rec_upper).each_with_index{ |rec_sa, id|
    sorted_lms[id] = lms[rec_sa]
  }

  return sa_is_induce(s, ls, sum_l, sum_s, sorted_lms)
end

# suffix array for array of integers or string
def suffix_array(s, upper = nil)
  if not upper then
  	case s
  	when Array
      # compression
      n = s.size
      idx = (0 ... n).sort_by{ |i| s[i] }
      t = [0]*n
      upper = 0
      t[idx[0]] = 0
      1.upto(n-1){ |i|
        upper += 1 if s[idx[i-1]] != s[idx[i]]
        t[idx[i]] = upper
      }
      s = t
    when String
      upper = 255
      s = s.chars.map(&:ord)
    end
  end
  return sa_is(s, upper)
end

# frozen_string_literal: true

# lcp array for array of integers or string
def lcp_array(s, sa)
  s = s.chars.map(&:ord) if s === String

  n = s.size
  rnk = [0]*n
  sa.each_with_index{ |sa, id|
    rnk[sa] = id
  }
  
  lcp = [0]*(n-1)
  h = 0
  n.times{ |i|
    h -= 1 if h > 0
    next if rnk[i] == 0
    j = sa[rnk[i]-1]
    h += 1 while j+h<n && i+h<n && s[j+h]==s[i+h]
    lcp[rnk[i]-1] = h
  }
  return lcp
end

s = gets.chomp
lcp = lcp_array(s, suffix_array(s))
ans = s.size*(s.size+1)/2
lcp.each{ |lcp| ans -= lcp }
puts ans