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 Rust (1.15.1) (judge verdict: Accepted)

use std::cmp::min;
use std::collections::HashSet;

#[allow(dead_code)]
fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}

#[allow(dead_code)]
fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}

fn main() {
    let n = read::<usize>();
    let s = read::<String>();
    let s1: Vec<char> = s.chars().collect();

    let answer = solve(n, s, &s1);
    println!("{}", answer);
}

fn solve(n: usize, s: String, s1: &[char]) -> usize {
    let mut v_max = 0;
    for i in 0..n {
        let s2 = &s1[i..n];
        let z = z_algo(s2.len(), s2);
        //println!("z: {:?}", z);
        let tmp = get_max(z.len(), &z);
        //println!("tmp: {}", tmp);
        if tmp > v_max {
            v_max = tmp;
        }
        if v_max > (n - i - 1) / 2 {
            break;
        }
    }
    return v_max;
}

fn z_algo(n: usize, s: &[char]) -> Vec<usize> {
    //println!("*** {}, {:?}", n, s);
    let mut z: Vec<usize> = vec![0; n];
    let mut l: usize = 0;
    let mut r: usize = 0;
    for i in 1..n {
        //println!("{}", i);
        if i >= r {
            //println!("   A");
            l = i;
            r = i;
            while r < n && s[r] == s[r - l] {
                r += 1;
            }
            z[i] = r - l;
        //r -= 1;
        } else {
            let k = i - l;
            if z[k] < r - i {
                //println!("   B1");
                z[i] = z[k];
            } else {
                //println!("   B2");
                l = i;
                while r < n && s[r] == s[r - l] {
                    r += 1;
                }
                z[i] = r - l;
            }
        }
    }
    // println!("{:?}", z);
    return z;
}

/**
 * l1 + len <= l2
 *  --> z[i] <= l1
 */
fn get_max(n: usize, z: &[usize]) -> usize {
    let mut v_max: usize = 0;
    for i in 1..n {
        let tmp = min(z[i], i);
        if tmp > v_max {
            v_max = tmp;
        }
    }
    return v_max;
}