Problem:
Score : 500 points

Problem Statement

Given is a string S of length N.

Find the maximum length of a non-empty string that occurs twice or more in S as contiguous substrings without overlapping.

More formally, find the maximum positive integer len such that there exist integers l_1 and l_2 ( 1 \leq l_1, l_2 \leq N - len + 1 ) that satisfy the following:

l_1 + len \leq l_2

S[l_1+i] = S[l_2+i] (i = 0, 1, ..., len - 1)

If there is no such integer len, print 0.

Constraints

2 \leq N \leq 5 \times 10^3

|S| = N

S consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the maximum length of a non-empty string that occurs twice or more in S as contiguous substrings without overlapping. If there is no such non-empty string, print 0 instead.

Sample Input 1

5
ababa

Sample Output 1

2

The strings satisfying the conditions are: a, b, ab, and ba. The maximum length among them is 2, which is the answer.
Note that aba occurs twice in S as contiguous substrings, but there is no pair of integers l_1 and l_2 mentioned in the statement such that l_1 + len \leq l_2.

Sample Input 2

2
xy

Sample Output 2

0

No non-empty string satisfies the conditions.

Sample Input 3

13
strangeorange

Sample Output 3

5

Solution in Scala (2.11.7) (judge verdict: Time Limit Exceeded)

import java.io._
import java.util.StringTokenizer
import scala.util.control.Breaks.{breakable,break}
import scala.collection.mutable.{Map, Queue, PriorityQueue}

object Main extends App {
  val in = new InputReader(System.in)
  val pw = new PrintWriter(System.out)

  val N = in.next().toInt
  private[this] val S = "0" + in.next()


  //
  private[this] def check(end: Int, begin: Int): Boolean = {
    val a = S.substring(begin, end+1)
    val b = S.substring(end+1, N+1)

    b.contains(a)
  }

  // 条件を満たす最大の値を返す
  private[this] def binarySearch(min: Int, max: Int, begin: Int): Int = {
    val mid: Int = (max + min) / 2
      (max - min) match{
      case 0 | 1 =>
        check(max, begin) match{
          case true  => max
          case false => min
        }
      case _ =>
        (check(mid, begin)) match{
          case true  => binarySearch(mid, max, begin)
          case false => binarySearch(min, mid, begin)
        }
    }
  }



  private[this] var ans = 0
  for (i <- 1 to N-1) {
    if (check(i, i)) {
      val tmp = binarySearch(i, i + (N-i) / 2, i) - (i-1)
      ans = Math.max(ans, tmp)
    }
  }
  println(ans)
}


class InputReader(stream: InputStream) {
  private[this] val reader = new BufferedReader(new InputStreamReader(stream))
  private[this] var tokenizer: StringTokenizer = new StringTokenizer(reader.readLine())
  def next(): String = {
    while (!tokenizer.hasMoreTokens()) {
      tokenizer = new StringTokenizer(reader.readLine())
    }
    tokenizer.nextToken()
  }
}