<p>Given a string <code>s</code>, consider all <em>duplicated substrings</em>: (contiguous) substrings of s that occur 2 or more times.&nbsp;The occurrences&nbsp;may overlap.</p>

<p>Return <strong>any</strong> duplicated&nbsp;substring that has the longest possible length.&nbsp;If <code>s</code> does not have a duplicated substring, the answer is <code>&quot;&quot;</code>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<pre><strong>Input:</strong> s = "banana"
<strong>Output:</strong> "ana"
</pre><p><strong class="example">Example 2:</strong></p>
<pre><strong>Input:</strong> s = "abcd"
<strong>Output:</strong> ""
</pre>
<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>2 &lt;= s.length &lt;= 3 * 10<sup>4</sup></code></li>
	<li><code>s</code> consists of lowercase English letters.</li>
</ul>

def suffixarray(s):
    n = len(s)
    rank = [0]*n
    sub = sorted((s[i],s[i+1] if i+1 < n else '',i) for i in range(n))
    l = 2
    while l < n:
        rank[sub[0][2]] = 1
        for (l1,r1,i1),(l2,r2,i2) in pairwise(sub):
            rank[i2] = rank[i1]+(l1 != l2 or r1 != r2)
        if rank[sub[-1][2]] == n:
            break
        sub = sorted((rank[i],rank[i+l] if i+l < n else 0,i) for i in range(n))
        l *= 2
    return [i for l,r,i in sub]

def lcp(s,sa):
    n = len(s)
    rank = [0]*n
    for i in range(n):
        rank[sa[i]] = i
    lcp_arr = [0]*n
    l = 0
    for i in range(n):
        if rank[i]:
            j = sa[rank[i]-1]
            while i+l < n and j+l < n and s[i+l] == s[j+l]:
                l += 1
            lcp_arr[rank[i]] = l
            l = max(0,l-1)
    return lcp_arr

class Solution:
    def longestDupSubstring(self, s: str) -> str:
        sa = suffixarray(s)
        m = -1
        for i,l in enumerate(lcp(s,sa)):
            if l > m:
                m = l
                im = i
        return s[sa[im]:sa[im]+m]
25200