unittest
{
	assert( [ "5", "ababa" ].parse.expand.solve == 2 );
	assert( [ "2", "xy" ].parse.expand.solve == 0 );
	assert( [ "13", "strangeorange" ].parse.expand.solve == 5 );
}



import std.algorithm;
import std.conv;
import std.range;
import std.stdio;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	input.popFront;
	auto s = input.front.to!( dchar[] );
	return tuple( s );
}

auto solve( dchar[] s )
{
	auto ans = 0L;
	foreach( a; 0L .. s.length.signed )
	{
		foreach( i, l; s[ a .. $ ].z_algorithm )
		{
			l = min( i, l );		// 重複個所を除く
			ans = max( ans, l );
		}
	}
	return ans;
}



// 最長共通接頭辞の長さ（s[ 0 .. l ] == s[ b .. l ] が成り立つbごとのlの最大値）
auto z_algorithm( dchar[] s )
{
	auto zs = new long[ s.length ];
	zs[ 0 ] = s.length;
	for( auto b = 1L, l = 0L; b < s.length; /* nop */ )
	{
		while( b + l < s.length && s[ l ] == s[ b + l ] ) l++;
		zs[ b ] = l;
		if( l == 0 )
		{
			b++;
			continue;
		}
		
		auto c = 1L;
		while( b + c < s.length && zs[ c ] + c < l )
		{
			zs[ b + c ] = zs[ c ];
			c++;
		}
		b += c;
		l -= c;
	}
	return zs;
}
