stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <bits/stdc++.h>

#define mp make_pair

#define ff first

#define ss second

using namespace std;

typedef long long LL;

typedef pair<LL, LL> PLL;

typedef pair<int, int> PII;

 

const PLL M = mp(1e9+7, 1e9+9);        ///Should be large primes

const LL base = 875329;               ///Should be a prime larger than highest value

const int N = 1e5+7;                 ///Highest length of string

 

ostream& operator<<(ostream& os, PLL hash) {

    return os<<"("<<hash.ff<<", "<<hash.ss<<")";

}

 

PLL operator+ (PLL a, LL x)     {return mp(a.ff + x, a.ss + x);}

PLL operator- (PLL a, LL x)     {return mp(a.ff - x, a.ss - x);}

PLL operator* (PLL a, LL x)     {return mp(a.ff * x, a.ss * x);}

PLL operator+ (PLL a, PLL x)    {return mp(a.ff + x.ff, a.ss + x.ss);}

PLL operator- (PLL a, PLL x)    {return mp(a.ff - x.ff, a.ss - x.ss);}

PLL operator* (PLL a, PLL x)    {return mp(a.ff * x.ff, a.ss * x.ss);}

PLL operator% (PLL a, PLL m)    {return mp(a.ff % m.ff, a.ss % m.ss);}

 

PLL pb[N];      ///powers of base mod M

///Call pre before everything

void pre() {

    pb[0] = mp(1,1);

    for (int i=1; i<N; i++)

        pb[i] = (pb[i-1] * base)%M;

}

 

///Calculates hashes of all prefixes of s including empty prefix

vector<PLL> hashList(string &s) {

    int n = s.size();

    vector<PLL> ans(n+1);

    ans[0] = mp(0,0);

 

    for (int i=1; i<=n; i++)

        ans[i] = (ans[i-1] * base + s[i-1])%M;

    return ans;

}

 

///Calculates hash of substring s[l..r] (1 indexed)

PLL Hash(vector<PLL> &hashlist, int l, int r) {

    int len = (r-l+1);

    return ((hashlist[r] - hashlist[l-1]*pb[len])%M+M)%M;

}

vector<PLL>hashVec;

int n; 

bool ok(int len) {



    for(int i =1 ; i+len-1 <= n ; i++ ) {

        

        PLL val1 = Hash(hashVec , i , i+len-1);

        

        for(int j = i+len ; j+len-1 <=n ; j++ ) {

            

            PLL val2 = Hash(hashVec , j , j+len-1);

            if(val1 == val2) return true;

        }

    }

    return false;

}





int main() {

    

    ios::sync_with_stdio(false);

    cin.tie(0);

    pre();

    

    

    string str;

    

    cin>>n>>str;

    

    hashVec = hashList(str);

    

    int lo = 0 , hi = n;

    int ans = 0;

    

    while(lo <= hi) {

        

        int mid = (lo+hi)/2;

        

        if(ok(mid)) {

            ans = mid;

            lo = mid+1;

        }

        else hi = mid-1;

    }

    cout<<ans<<'\n';

    return 0;

    



}

// Faster C++ solution for the same problem (measured speedup: 3.605657477778395x):
#include<bits/stdc++.h>

using namespace std;

#define N 5010

int f[N][N], n;

string s;



int main() {

    cin >> n >> s;

    int ans = 0;

    for(int i = n - 1; i >= 0; i--)

        for(int j = n - 1; j >= 0; j--) {

            if (s[i] == s[j]) f[i][j] = max(f[i][j], f[i + 1][j + 1] + 1);

            ans = max(ans, min(f[i][j], j - i));

        }

    cout << ans << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define mp make_pair

#define ff first

#define ss second

using namespace std;

typedef long long LL;

typedef pair<LL, LL> PLL;

typedef pair<int, int> PII;

 

const PLL M = mp(1e9+7, 1e9+9);        ///Should be large primes

const LL base = 875329;               ///Should be a prime larger than highest value

const int N = 1e5+7;                 ///Highest length of string

 

ostream& operator<<(ostream& os, PLL hash) {

    return os<<"("<<hash.ff<<", "<<hash.ss<<")";

}

 

PLL operator+ (PLL a, LL x)     {return mp(a.ff + x, a.ss + x);}

PLL operator- (PLL a, LL x)     {return mp(a.ff - x, a.ss - x);}

PLL operator* (PLL a, LL x)     {return mp(a.ff * x, a.ss * x);}

PLL operator+ (PLL a, PLL x)    {return mp(a.ff + x.ff, a.ss + x.ss);}

PLL operator- (PLL a, PLL x)    {return mp(a.ff - x.ff, a.ss - x.ss);}

PLL operator* (PLL a, PLL x)    {return mp(a.ff * x.ff, a.ss * x.ss);}

PLL operator% (PLL a, PLL m)    {return mp(a.ff % m.ff, a.ss % m.ss);}

 

PLL pb[N];      ///powers of base mod M

///Call pre before everything

void pre() {

    pb[0] = mp(1,1);

    for (int i=1; i<N; i++)

        pb[i] = (pb[i-1] * base)%M;

}

 

///Calculates hashes of all prefixes of s including empty prefix

vector<PLL> hashList(string &s) {

    int n = s.size();

    vector<PLL> ans(n+1);

    ans[0] = mp(0,0);

 

    for (int i=1; i<=n; i++)

        ans[i] = (ans[i-1] * base + s[i-1])%M;

    return ans;

}

 

///Calculates hash of substring s[l..r] (1 indexed)

PLL Hash(vector<PLL> &hashlist, int l, int r) {

    int len = (r-l+1);

    return ((hashlist[r] - hashlist[l-1]*pb[len])%M+M)%M;

}

vector<PLL>hashVec;

int n; 

bool ok(int len) {



    for(int i =1 ; i+len-1 <= n ; i++ ) {

        

        PLL val1 = Hash(hashVec , i , i+len-1);

        

        for(int j = i+len ; j+len-1 <=n ; j++ ) {

            

            PLL val2 = Hash(hashVec , j , j+len-1);

            if(val1 == val2) return true;

        }

    }

    return false;

}





int main() {

    

    ios::sync_with_stdio(false);

    cin.tie(0);

    pre();

    

    

    string str;

    

    cin>>n>>str;

    

    hashVec = hashList(str);

    

    int lo = 0 , hi = n;

    int ans = 0;

    

    while(lo <= hi) {

        

        int mid = (lo+hi)/2;

        

        if(ok(mid)) {

            ans = mid;

            lo = mid+1;

        }

        else hi = mid-1;

    }

    cout<<ans<<'\n';

    return 0;

    



}

// Faster C++ solution for the same problem (measured speedup: 3.561575130696862x):
#include<bits/stdc++.h>

using namespace std;



#define N 5000 + 10

int f[N][N],n,ans;

char s[N];



int main(){

ios::sync_with_stdio(false);

cin>>n>>s;

for(int i=n-1;i>=0;i--)

for(int j=n-1;j>=0;j--){

if(s[i]==s[j])

f[i][j]=max(f[i][j],f[i+1][j+1]+1);

ans=max(ans,min(f[i][j],j-i));

}

cout<<ans;

}
// Slower C++ solution:
#include<iostream>

#include<cstdio>

#include<vector>

using namespace std;

char s[5005];

int Next[5005];

vector<char> v[5005];

int main()

{

    int n,i,j,k,m,t,max=0;

    scanf("%d%s",&n,s);

    for(i=0;i<n;i++)

        for(j=i;j<n;j++)

            v[i].push_back(s[j]);

    for(i=0;i<n;i++)

    {

        Next[0]=-1;

        j=0;

        k=-1;

        while(j<n-i)

        {

            if(k==-1||v[i][j]==v[i][k])

                Next[++j]=++k;

            else

                k=Next[k];

        }

        for(j=0;j<=n-i;j++)

        {

            if(Next[j]<=j/2)

            {

                if(Next[j]>max) max=Next[j];

            }

            else

            {

                t=j-Next[j];

                t=t*(j/t/2);

                if(t>max) max=t;

            }

        }

    }

    printf("%d\n",max);

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.1127146423145802x):
#include<bits/stdc++.h>

using namespace std;



#define N 5000 + 10

int f[N][N],n,ans;

char s[N];



int main(){

ios::sync_with_stdio(false);

cin>>n>>s;

for(int i=n-1;i>=0;i--)

for(int j=n-1;j>=0;j--){

if(s[i]==s[j])

f[i][j]=max(f[i][j],f[i+1][j+1]+1);

ans=max(ans,min(f[i][j],j-i));

}

cout<<ans;

}
// Slower C++ solution:
#include<iostream>

#include<cstdio>

#include<vector>

using namespace std;

char s[5005];

int Next[5005];

vector<char> v[5005];

int main()

{

    int n,i,j,k,t,max=0;

    scanf("%d%s",&n,s);

    for(i=0;i<n;i++)

        for(j=i;j<n;j++)

            v[i].push_back(s[j]);

    for(i=0;i<n;i++)

    {

        Next[0]=-1;

        j=0;

        k=-1;

        while(j<n-i)

        {

            if(k==-1||v[i][j]==v[i][k])

                Next[++j]=++k;

            else

                k=Next[k];

        }

        for(j=0;j<=n-i;j++)

        {

            if(Next[j]<=j/2)

            {

                if(Next[j]>max) max=Next[j];

            }

            else

            {

                t=j-Next[j];

                t=t*(j/t/2);

                if(t>max) max=t;

            }

        }

    }

    printf("%d\n",max);

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 1.1127529961372589x):
#include<bits/stdc++.h>

using namespace std;



#define N 5000 + 10

int f[N][N],n,ans;

char s[N];



int main(){

ios::sync_with_stdio(false);

cin>>n>>s;

for(int i=n-1;i>=0;i--)

for(int j=n-1;j>=0;j--){

if(s[i]==s[j])

f[i][j]=max(f[i][j],f[i+1][j+1]+1);

ans=max(ans,min(f[i][j],j-i));

}

cout<<ans;

}
// Slower C++ solution:
#include <cstdio>

#include <cctype>

#include <algorithm>

#include <cstring>

#include <set>

int read(){

	register int x = 0;

	register char ch = getchar(), f = 1;

	for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = !f;

	for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0');

	return f ? x : -x;

}

#define N 5005

const int B1 = 233, P1 = 382538579, B2 = 331, P2 = 952959323;

int pw1[N], pw2[N];

struct node{

	int H1, H2;

	node(int _H1 = 0, int _H2 = 0){ H1 = _H1, H2 = _H2; }

	bool operator < (const node &rhs) const {

		return H1 < rhs.H1 || (H1 == rhs.H1 && H2 < rhs.H2);

	}

	bool operator == (const node &rhs) const {

		return H1 == rhs.H1 && H2 == rhs.H2;

	}

	node operator + (const char ch) const {

		return node((1ll * H1 * B1 + ch) % P1, (1ll * H2 * B2 + ch) % P2);

	}

	node operator - (const node &rhs) const {

		return node((H1 - rhs.H1 + P1) % P1, (H2 - rhs.H2 + P2) % P2);

	}

	node operator << (const int x) const {

		return node(1ll * H1 * pw1[x] % P1, 1ll * H2 * pw2[x] % P2);

	}

}h[N];

int n;

char a[N];

int main(){

	scanf("%d%s", &n, a + 1);

	pw1[0] = pw2[0] = 1;

	for (register int i = 1; i <= n; ++i)

		pw1[i] = 1ll * pw1[i - 1] * B1 % P1, pw2[i] = 1ll * pw2[i - 1] * B2 % P2;

	for (register int i = 1; i <= n; ++i) h[i] = h[i - 1] + a[i];

	for (register int len = n >> 1; len; --len){

		std :: set<node> S;

		for (register int i = len << 1; i <= n; ++i){

			S.insert(h[i - len] - (h[i - (len << 1)] << len));

			if (S.count(h[i] - (h[i - len] << len))) return printf("%d\n", len), 0;

		}

	}

	printf("0\n");

}


// Faster C++ solution for the same problem (measured speedup: 5.091981719981004x):
#include <cstdio>

#include <cstring>

#include <algorithm>

#define N 5005

int n, ans;

char a[N];

int main(){

	scanf("%d%s", &n, a + 1);

	for (register int i = 1; i <= n; ++i){

		int s = 0;

		for (register int j = 1; j <= n - i; ++j)

			a[j] == a[j + i] && s < i ? ++s, ans = std :: max(ans, s) : s = 0;

	}

	printf("%d\n", ans);

}
// Slower C++ solution:
#include <cstdio>

#include <map>

#include <vector>

const int HASH = 131;

const int MAXN = 5005;

const int MOD = 1e9+7;

char S[MAXN];

int H[MAXN];

int N, size;



std::map<int, std::vector<int>> D;



bool compare(int a, int b) {

  for (int k = 0; k < size; ++k) {

    if (S[a-k] != S[b-k]) return false;

  }

  return true;

}



bool matches(int sum, int cur) {

  for (int pos: D.at(sum)) {

    if (pos + size > cur) break;

    if (compare(pos, cur)) {

      return true;

    }

  }

  return false;

}



bool find() {

  D.clear();

  int sum = 0;

  for (int i = 0; i < N; ++i) {

    sum = (1LL * HASH * sum + S[i]) % MOD;

    if (i >= size) {

      int old = 1LL * H[size] * S[i-size] % MOD;

      sum = (sum - old + MOD) % MOD;

    }

    if (i+1 >= size) {

      if (D.count(sum) && matches(sum, i)) {

        return true;

      }

      D[sum].push_back(i);

    }

  }

  return false;

}



void init() {

  H[0] = 1;

  for (int i = 1; i <= N; ++i) {

    H[i] = 1LL * H[i-1] * HASH % MOD;

  }

}



int solve() {

  int lo = 0;

  int hi = N/2;

  while (lo < hi) {

    size = (lo + hi + 1) / 2;

    if (find()) {

      lo = size;

    } else {

      hi = size-1;

    }

  }

  return lo;

}



int main() {

  scanf(" %d%s", &N, S);

  init();

  printf("%d\n", solve());

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 4.859939183976685x):
#include <algorithm>

#include <cstdio>

const int MAXN = 5005;

char S[MAXN];

int dp[MAXN][MAXN];

int N;



int solve() {

  for (int i = 0; i <= N; ++i) {

    dp[i][0] = dp[0][i] = 0;

  }

  int ret = 0;

  for (int i = 1; i <= N; ++i) {

    for (int j = 1; j <= N; ++j) {

      if ((i == j) || (S[i] != S[j])) {

        dp[i][j] = 0;

      } else if (S[i] == S[j]) {

        dp[i][j] = std::min(dp[i-1][j-1] + 1, std::abs(i - j));

        ret = std::max(dp[i][j], ret);

      }

    }

  }

  return ret;

}



int main() {

  scanf(" %d%s", &N, S+1);

  printf("%d\n", solve());

  return 0;

}
// Slower C++ solution:
#include <cstdio>

#include <map>

#include <vector>

const int HASH = 131;

const int MAXN = 5005;

const int MOD = 1e9+7;

char S[MAXN];

int H[MAXN];

int N, size;



std::map<int, std::vector<int>> D;



bool compare(int a, int b) {

  for (int k = 0; k < size; ++k) {

    if (S[a-k] != S[b-k]) return false;

  }

  return true;

}



bool matches(int sum, int cur) {

  for (int pos: D.at(sum)) {

    if (pos + size > cur) break;

    if (compare(pos, cur)) {

      return true;

    }

  }

  return false;

}



bool find() {

  D.clear();

  int sum = 0;

  for (int i = 0; i < N; ++i) {

    sum = (1LL * HASH * sum + S[i]) % MOD;

    if (i >= size) {

      int old = 1LL * H[size] * S[i-size] % MOD;

      sum = (sum - old + MOD) % MOD;

    }

    if (i+1 >= size) {

      if (D.count(sum) && matches(sum, i)) {

        return true;

      }

      D[sum].push_back(i);

    }

  }

  return false;

}



void init() {

  H[0] = 1;

  for (int i = 1; i <= N; ++i) {

    H[i] = 1LL * H[i-1] * HASH % MOD;

  }

}



int solve() {

  int lo = 0;

  int hi = N/2;

  while (lo < hi) {

    size = (lo + hi + 1) / 2;

    if (find()) {

      lo = size;

    } else {

      hi = size-1;

    }

  }

  return lo;

}



int main() {

  scanf(" %d%s", &N, S);

  init();

  printf("%d\n", solve());

  return 0;

}

// Faster C++ solution for the same problem (measured speedup: 4.858484026434838x):
#include <algorithm>

#include <cstdio>

const int MAXN = 5005;

char S[MAXN];

int dp[MAXN][MAXN];

int N;



int solve() {

  for (int j = 0; j <= N; ++j) {

    dp[0][j] = 0;

  }

  int ret = 0;

  for (int i = 1; i <= N; ++i) {

    for (int j = i; j <= N; ++j) {

      if ((i == j) || (S[i] != S[j])) {

        dp[i][j] = 0;

      } else if (S[i] == S[j]) {

        dp[i][j] = std::min(dp[i-1][j-1] + 1, j - i);

        ret = std::max(dp[i][j], ret);

      }

    }

  }

  return ret;

}



int main() {

  scanf(" %d%s", &N, S+1);

  printf("%d\n", solve());

  return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=5e3+5,mod=1e9+9;

ll hs[N],f[N],invf[N];

int n;

char s[N];

int get_hs(int l,int r)

{

    return (hs[r]-hs[l-1]+mod)%mod*invf[l-1]%mod;

}

map<int,int>vis;

bool judge(int m)

{

    if(m==0) return true;

    vis.clear();

    for(int i=n-m+1;i>=1;i--)

        vis[get_hs(i,i+m-1)]++;

    int pos=1;

    for(int i=1;i<=n-m+1;i++)

    {

        while(pos<=i+m-1&&pos<=n-m+1)

        {

            vis[get_hs(pos,pos+m-1)]--;pos++;

        }

        if(pos>n-m+1) return false;

        if(vis[get_hs(i,i+m-1)]) return true;

    }

    return false;

}

ll qpow(ll a,ll n)

{

    ll ans=1;

    while(n)

    {

        if(n&1) ans=ans*a%mod;

        a=a*a%mod;

        n>>=1;

    }

    return ans;

}

int main()

{

    f[0]=invf[0]=1;

    for(int i=1;i<N;i++)

        f[i]=f[i-1]*13331%mod,invf[i]=qpow(f[i],mod-2);

    scanf("%d%s",&n,s+1);

    for(int i=1;i<=n;i++)

        hs[i]=(hs[i-1]+(s[i]-'a')*f[i])%mod;

    int l=0,r=n/2,ans;

    while(l<=r)

    {

        int m=l+r>>1;

        if(judge(m)) ans=m,l=m+1;

        else r=m-1;

    }

    printf("%d\n",ans);

}


// Faster C++ solution for the same problem (measured speedup: 2.2233878709874673x):
#include<queue>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include <map>

#define key 2333

#define maxn 100005

#define uLL unsigned long long

using namespace std;

uLL hsh[maxn],bas[maxn];

map<uLL,int>h;

char s[maxn];

int n;

priority_queue<int> hep;

inline int read(){

	int ret=0,f=1;char ch=getchar();

	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}

	while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();

	return ret*f;

}

uLL gethashcode(int i,int p){

    return hsh[i+p-1]-hsh[i-1]*bas[p];

}

inline bool check(int p){

	h.clear();

	for(int i=1;i+p-1<=n;i++){

        uLL num = gethashcode(i,p);

        if(h[num]){

            if(h[num]+p<=i){

                return 1;

            }

        }

        else

            h[num]=i;

	}

	return 0;

}

int main(){

	n=read();

	scanf("%s",s+1);

	bas[0]=1;

	for (int i=1;i<=n;i++) hsh[i]=hsh[i-1]*key+s[i]-'a',bas[i]=bas[i-1]*key;

	int L=0,R=n/2,ret=0;

	while (L<=R){

		int mid=(L+R)>>1;

		if (check(mid)) ret=mid,L=mid+1;

		else R=mid-1;

	}

	printf("%d\n",ret);

	return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=5e3+5,mod=1e9+9;

ll hs[N],f[N],invf[N];

int n;

char s[N];

int get_hs(int l,int r)

{

    return (hs[r]-hs[l-1]+mod)%mod*invf[l-1]%mod;

}

map<int,int>vis;

bool judge(int m)

{

    if(m==0) return true;

    vis.clear();

    for(int i=n-m+1;i>=1;i--)

        vis[get_hs(i,i+m-1)]++;

    int pos=1;

    for(int i=1;i<=n-m+1;i++)

    {

        while(pos<=i+m-1&&pos<=n-m+1)

        {

            vis[get_hs(pos,pos+m-1)]--;pos++;

        }

        if(pos>n-m+1) return false;

        if(vis[get_hs(i,i+m-1)]) return true;

    }

    return false;

}

ll qpow(ll a,ll n)

{

    ll ans=1;

    while(n)

    {

        if(n&1) ans=ans*a%mod;

        a=a*a%mod;

        n>>=1;

    }

    return ans;

}

int main()

{

    f[0]=invf[0]=1;

    for(int i=1;i<N;i++)

        f[i]=f[i-1]*13331%mod,invf[i]=qpow(f[i],mod-2);

    scanf("%d%s",&n,s+1);

    for(int i=1;i<=n;i++)

        hs[i]=(hs[i-1]+(s[i]-'a')*f[i])%mod;

    int l=0,r=n/2,ans;

    while(l<=r)

    {

        int m=l+r>>1;

        if(judge(m)) ans=m,l=m+1;

        else r=m-1;

    }

    printf("%d\n",ans);

}


// Faster C++ solution for the same problem (measured speedup: 1.4783140343864913x):
#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <queue>

#include <map>

using namespace std;

typedef long long ll;

const ll mod = 1000000009;

const int p = 2333;

map<ll,int>has1;

ll hh[50015]={0};

ll pow1[50015]={0};

char s[50005]={0};

ll gethashcode(int i,int m){

    return (hh[i+m-1]-hh[i-1]*pow1[m]%mod+mod)%mod;

}

int n;

ll num;

int check(int m){

    has1.clear();

    for(int i=1;i+m-2<=n;i++){

        num=gethashcode(i,m);

       // cout << num <<endl;

        if(has1[num]){

            if(has1[num]+m<=i){

                return 1;

            }

        }

        else

            has1[num]=i;

    }

    return 0;

}

int main()

{

    pow1[0]=1;

    for(int i=1;i<50005;i++){

        pow1[i]=pow1[i-1]*p%mod;

    }

    scanf("%d",&n);

    scanf("%s",s+1);

    hh[0]=0;

    for(int i=1;i<=n;i++)

        hh[i]=(hh[i-1]*p%mod+s[i]-'a')%mod;

    int ans = 0 ;

    int l=1,r=n;

    while(l<r){

        int m=(l+r)/2;

        if(check(m)){

            ans=m;

            l=m+1;

        }

        else

            r=m;

    }

    printf("%d\n",ans);

    return 0;

}

//

//13

//orangerangeao
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N=5e3+5,mod=1e9+9;

ll hs[N],f[N],invf[N];

int n;

char s[N];

int get_hs(int l,int r)

{

    return (hs[r]-hs[l-1]+mod)%mod*invf[l-1]%mod;

}

map<int,int>vis;

bool judge(int m)

{

    if(m==0) return true;

    vis.clear();

    for(int i=n-m+1;i>=1;i--)

        vis[get_hs(i,i+m-1)]++;

    int pos=1;

    for(int i=1;i<=n-m+1;i++)

    {

        while(pos<=i+m-1&&pos<=n-m+1)

        {

            vis[get_hs(pos,pos+m-1)]--;pos++;

        }

        if(pos>n-m+1) return false;

        if(vis[get_hs(i,i+m-1)]) return true;

    }

    return false;

}

ll qpow(ll a,ll n)

{

    ll ans=1;

    while(n)

    {

        if(n&1) ans=ans*a%mod;

        a=a*a%mod;

        n>>=1;

    }

    return ans;

}

int main()

{

    f[0]=invf[0]=1;

    for(int i=1;i<N;i++)

        f[i]=f[i-1]*13331%mod,invf[i]=qpow(f[i],mod-2);

    scanf("%d%s",&n,s+1);

    for(int i=1;i<=n;i++)

        hs[i]=(hs[i-1]+(s[i]-'a')*f[i])%mod;

    int l=0,r=n/2,ans;

    while(l<=r)

    {

        int m=l+r>>1;

        if(judge(m)) ans=m,l=m+1;

        else r=m-1;

    }

    printf("%d\n",ans);

}


// Faster C++ solution for the same problem (measured speedup: 2.0613777960257385x):
#include <iostream>

#include <cstdio>

#include <algorithm>

#include <cstring>

#include <queue>

#include <map>

using namespace std;

typedef long long ll;

const int p = 13331;

map<ll,int>has1;

long long hh[5005]={0};

long long aa[5005]={0};

char s[5005]={0};

ll gethashcode(int i,int j){

    if(i==0)

        return hh[j];

    else

    return hh[j]-hh[i-1]*aa[j-i+1];

}

int n;

bool check(int m){

        has1.clear();

        ll num;

        for(int i=1;i+m-2<=n;i++){

        num=gethashcode(i,i+m-1);

        if(has1[num]){

            if(has1[num]<=i-m)

                return 1;

            //cout << i << " " << has1[num] << endl;

        }

        else

            has1[num]=i;

    }

    return 0;

}

int main()

{

    cin >> n;

    cin >> s;

    ll num;

    aa[0]=0;

    for(int i=0;i<n;i++){

        hh[i+1]=hh[i]*p+s[i]-'a';

    }

    aa[0]=1;

    for(int i=1;i<=n;i++)

        aa[i]=aa[i-1]*p;

    int res=0;

    int l=0,r=n;

    int mid;

    int flag=0;

    //cout << check(5) << endl;

    while(l<r){

        mid=(l+r)/2;

        if(check(mid)){

            res=mid;

            l=mid+1;

        }

        else

            r=mid;

    }

    printf("%d\n",res);

    return 0;

}