class Sa
  attr_reader :suf, :string

  def initialize(string)
    @string = string
    @suf = (0..string.size-1).sort_by{|i|@string[i..-1]}
  end

  def suffix(idx)
   @string[@suf[idx]..@string.size-1]
  end

  def bsearch(str)
    low = 0
    high = @suf.length-1
    found = nil
    while(low <= high) do
      mid = (low + high) / 2
      comp = suffix(mid)
      case comp <=> str
      when 1
        high = mid - 1
      when -1 then
        low = mid + 1
      else
        found = comp
        low = high + 1
      end
    end
    found
  end
end

class Lcp
  attr_reader :lcp
  def initialize(s, sa)
    n = s.length
    l = Array.new(n, 0)
    r = Array.new(n, 0)

    n.times {|i| r[sa[i]] = i}

    h = 0
    l[0] = 0
    n.times do |i|
      j = sa[r[i].pred]
      h = h.pred if h.positive?
      while j + h < n && i + h < n
        break unless s[j + h] == s[i + h]
        h = h.next
      end
      l[r[i].pred] = h
    end

    @lcp = l
  end
end

N = gets.to_i
S = gets.chomp

sa = Sa.new(S).suf
lcp = Lcp.new(S, sa).lcp

len = 0
S.length.times do |i|
  next unless sa[i] && sa[i.next] && sa[i] < S.length == sa[i.next] < S.length
  len = [len, lcp[i]].max
end

puts len
