import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class Main {

    public static void main(final String[] args) throws IOException {
        try(Scanner scan = new Scanner(System.in);
            PrintWriter print = new PrintWriter(System.out)) {
            final int n = scan.nextInt();
            final int m = scan.nextInt();
            final Pair<Integer, Integer>[] arcs = new Pair[m];
            for(int k = 0; k < m; ++k) {
                int i = scan.nextInt();
                int j = scan.nextInt();
                --i; --j;
                arcs[k] = new Pair(i, j);
            }
            print.println(calcMinNumStepsToCenterPermGraph(new DirectedGraph(n, arcs)));
        }
    }

    public static int calcMinNumStepsToCenterPermGraph(final DirectedGraph graph) {
        int result = Integer.MAX_VALUE;
        for(DirectedGraph.Vertex center : graph.vertices) {
            int num = 2 * graph.vertices.length - 1 - graph.getOutcomingArcs(center).size() -
                    graph.getIncomingArcs(center).size() + (graph.containsArc(center, center) ? 1 : 0);
            final int n = graph.vertices.length - 1;
            final List<Pair<Integer, Integer>> edges = CollectionFactory.createArrayList();
            for(DirectedGraph.Arc arc : graph.arcs) {
                if(!center.equals(arc.from) && !(center.equals(arc.to))) {
                    int i = arc.from.index;
                    int j = arc.to.index;
                    if(i > center.index) {
                        --i;
                    }
                    if(j > center.index) {
                        --j;
                    }
                    edges.add(new Pair(i, j));
                }
            }
            final int matching = GraphUtils.calcNumMatchingBipartite(n, n, edges);
            num += edges.size() - matching;
            num += n - matching;
            result = Math.min(result, num);
        }
        return result;
    }

    public static class GraphUtils {
        public static int calcNumMatchingBipartite(final int n, final int m, final List<Pair<Integer, Integer>> edges) {
            final MatchingBipartiteSolver solver = new MatchingBipartiteSolver(n, m, edges);
            return solver.solve();
        }

        private static class MatchingBipartiteSolver {
            private final int n;
            private final int m;
            private final List<Integer>[] edges;
            private final Integer[] match;
            private final boolean[] visited;

            public MatchingBipartiteSolver (final int n, final int m, final List<Pair<Integer, Integer>> edges) {
                this.n = n;
                this.m = m;
                this.edges = new List[n];
                for(int i = 0; i < n; ++i) {
                    this.edges[i] = CollectionFactory.createArrayList();
                }
                for(final Pair<Integer, Integer> edge: edges) {
                    this.edges[edge.first].add(edge.second);
                }
                match = new Integer[n + m];
                visited = new boolean[n + m];
            }

            public int solve() {
                int result = 0;
                for(;;) {
                    Arrays.fill(visited, false);
                    int gain = 0;
                    for(int i = 0; i < n; ++i) {
                        if(match[i] == null && !visited[i] && tryMatch(i)) {
                            ++gain;
                        }
                    }
                    if(gain > 0) {
                        result += gain;
                    } else {
                        break;
                    }
                }
                return result;
            }

            private boolean tryMatch(final int i) {
                visited[i] = true;
                for(int j : edges[i]) {
                    if(!visited[j + n]) {
                        visited[j + n] = true;
                        final Integer k = match[j + n];
                        if(k == null || (!visited[k] && tryMatch(k))) {
                            match[j + n] = i;
                            match[i] = j + n;
                            return true;
                        }
                    }
                }
                return false;
            }
        }
    }

    public static class DirectedGraph {
        public static class Vertex {
            public final int index;

            public Vertex(int index) {
                this.index = index;
            }

            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;

                Vertex vertex = (Vertex) o;

                if (index != vertex.index) return false;

                return true;
            }

            @Override
            public int hashCode() {
                return index;
            }
        }

        public static class Arc {
            public final Vertex from;
            public final Vertex to;

            public Arc(Vertex from, Vertex to) {
                this.from = from;
                this.to = to;
            }

            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (o == null || getClass() != o.getClass()) return false;

                Arc arc = (Arc) o;

                if (!from.equals(arc.from)) return false;
                if (!to.equals(arc.to)) return false;

                return true;
            }

            @Override
            public int hashCode() {
                int result = from.hashCode();
                result = 31 * result + to.hashCode();
                return result;
            }
        }

        final public Vertex[] vertices;
        final public Arc[] arcs;

        public DirectedGraph(final int n, final Pair<Integer, Integer>[] arcs) {
            vertices = new Vertex[n];
            this.arcs = new Arc[arcs.length];
            for(int i = 0; i < n; ++i) {
                vertices[i] = new Vertex(i);
            }
            for(int i = 0; i < arcs.length; ++i) {
                this.arcs[i] = new Arc(vertices[arcs[i].first], vertices[arcs[i].second]);
            }
        }

        public List<Arc> getOutcomingArcs(final Vertex v) {
            final List<Arc> result = CollectionFactory.createArrayList();
            for(Arc arc : arcs) {
                if(arc.from.equals(v)) {
                    result.add(arc);
                }
            }
            return result;
        }

        public List<Arc> getIncomingArcs(final Vertex v) {
            final List<Arc> result = CollectionFactory.createArrayList();
            for(Arc arc : arcs) {
                if(arc.to.equals(v)) {
                    result.add(arc);
                }
            }
            return result;
        }

        public boolean containsArc(final Vertex from, final Vertex to) {
            for(Arc arc : arcs) {
                if(arc.from.equals(from) && arc.to.equals(to)) {
                    return true;
                }
            }
            return false;
        }
    }

    public static class MatrixIntMod {
        final int mod;
        final int[][] data;

        public MatrixIntMod(final int n, final int m, final int mod) {
            this.mod = mod;
            this.data = new int[n][m];
            for(int i = 0; i < n; ++i) {
                Arrays.fill(data[i], 0);
            }
        }

        public MatrixIntMod(final int[][] data, final int mod) {
            this(data.length, data[0].length, mod);
            for(int i = 0; i < data.length; ++i) {
                for(int j = 0; j < data[i].length; ++j) {
                    this.data[i][j] = ModNumberUtils.norm(mod, data[i][j]);
                }
            }
        }

        public MatrixIntMod(final int[] data, final int mod) {
            this(data.length, 1, mod);
            for(int i = 0; i < data.length; ++i) {
                this.data[i][0] = ModNumberUtils.norm(mod, data[i]);
            }
        }

        public int[] all() {
            int n = data.length;
            int m = data[0].length;
            final int[] res = new int[n * m];
            int k = 0;
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < m; ++j) {
                    res[k++] = data[i][j];
                }
            }
            return res;
        }

        public MatrixIntMod mult(final MatrixIntMod val) {
            if(data[0].length != val.data.length) throw new RuntimeException("dimensions for mult are wrong");
            final int n = data.length;
            final int m = data[0].length;
            final int l = val.data[0].length;
            final MatrixIntMod res = new MatrixIntMod(n, l, mod);
            for(int i = 0; i < n; ++i) {
                for(int j = 0; j < l; ++j) {
                    for(int k = 0; k < m; ++k) {
                        res.data[i][j] = ModNumberUtils.add(mod, res.data[i][j],
                                ModNumberUtils.mult(mod, data[i][k], val.data[k][j]));
                    }
                }
            }
            return res;
        }

        public int[] mult(final int[] ar) {
            return mult(new MatrixIntMod(ar, mod)).all();
        }

        public MatrixIntMod power(final long t) {
            if(t == 0) return eye(data.length, mod);
            MatrixIntMod res = power(t >> 1);
            res = res.mult(res);
            if((t & 1) == 1) {
                res = res.mult(this);
            }
            return res;
        }

        public static MatrixIntMod eye(final int n, final int mod) {
            final MatrixIntMod res = new MatrixIntMod(n, n, mod);
            if(mod > 1) {
                for(int i = 0; i < n; ++i) {
                    res.data[i][i] = 1;
                }
            }
            return res;
        }
    }

    public static class ModNumberUtils {
        public static int add(int mod, int a, int b) {
            a += b;
            if(a >= mod) {
                a -= mod;
            }
            return a;
        }

        public static int norm(int mod, int a) {
            a %= mod;
            if(a < 0) {
                a += mod;
            }
            return a;
        }

        public static int mult(int mod, int a, int b) {
            return (int)((long)a * b % mod);
        }
    }

    public static class Pair<X, Y>{
        public X first;
        public Y second;

        public Pair(final X first, final Y second) {
            this.first = first;
            this.second = second;
        }
    }

    public static class NumberUtils {
        public static interface Factorizer {
            List<Integer> factorize(int number);
        }

        /**
         * thread safe Factorizer
         */
        public static Factorizer createSmallNumberFactorizer(final int upperBound) {
            return new SmallNumberFactorizer(upperBound);
        }

        /**
         * thread safe
         */
        private static class SmallNumberFactorizer implements Factorizer {
            private int[] divisors;
            private final int upperBound;
            private boolean prepared = false;

            /**
             * lazy
             * time complexity O(n * log(n) * log(log(n))
             * memory complexity O(n)
             */
            public SmallNumberFactorizer(final int upperBound) {
                this.upperBound = upperBound;
            }

            private synchronized void prepare() {
                divisors = new int[upperBound];
                Arrays.fill(divisors, 0);
                for(int i = 2; i * i < upperBound; ++i) {
                    if(divisors[i] == 0) {
                        for(int j = i * i; j < upperBound; j += i) {
                            if(divisors[j] == 0) {
                                divisors[j] = i;
                            }
                        }
                    }
                }
                prepared = true;
            }

            /**
             * complexity O(result)
             */
            public List<Integer> factorize(int number) {
                synchronized (this) {
                    if(!prepared) {
                        prepare();
                    }
                }
                final List<Integer> result = CollectionFactory.createArrayList();
                if(number < 2) return result;
                if(number >= upperBound) throw new RuntimeException("number should be less than upper bound");
                while(divisors[number] > 0) {
                    result.add(divisors[number]);
                    number /= divisors[number];
                }
                result.add(number);
                return result;
            }
        }
    }

    public static class CollectionFactory {
        public static<T> List<T> createArrayList() {
            return new ArrayList<>();
        }

        public static<T> List<T> createArrayList(final int capacity) {
            return new ArrayList<>(capacity);
        }
    }

    public static class CollectionUtils {
        public static<T> List<T> unique(final List<T> list) {
            final List<T> result = CollectionFactory.createArrayList();
            T p = null;
            for(T elem : list) {
                if(!elem.equals(p)) {
                    result.add(elem);
                    p = elem;
                }
            }
            return result;
        }

        public static<T extends Comparable<T>> T max(final List<T> list, final T lowerBound) {
            T result = lowerBound;
            for(T elem : list) {
                if(elem.compareTo(result) > 0) {
                    result = elem;
                }
            }
            return result;
        }
    }

}


import java.io.*;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.sql.Time;
import java.util.*;

import java.math.BigInteger;

import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;

public class Main{

    void run(){
        Locale.setDefault(Locale.US);
        boolean oj = System.getProperty("ONLINE_JUDGE") != null;
//        boolean oj = true;
        try{
            if( oj ){
                sc  = new FastScanner( new InputStreamReader(System.in  ) );
                out = new PrintWriter(   new OutputStreamWriter(System.out) );
            } else{
                sc  = new FastScanner(new FileReader("in.txt") );
//                sc  = new FastScanner(new FileReader("D:\\JavaOlymp\\FatalError\\output.txt") );
                out = new PrintWriter(   new FileWriter("out.txt") );
            }
        } catch (Exception e) {
            System.exit(-1);
        }
        long tB = System.currentTimeMillis();
        solve();
        if( !oj ) System.err.println( "Time: " + (System.currentTimeMillis()-tB)/1e3 );
        out.flush();
    }

    class FastScanner{
        BufferedReader br;
        StringTokenizer st = new StringTokenizer("");
        FastScanner( InputStreamReader a ){
            br = new BufferedReader(a);
        }
        FastScanner( FileReader a ){
            br = new BufferedReader(a);
        }
        String next(){
            while( !st.hasMoreTokens() )
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    return null;
                }
            return st.nextToken();
        }
        String readLine(){
            try {
                return br.readLine();
            } catch (Exception e) {
                return null;
            }
        }
        int nextInt(){ return Integer.parseInt(next()); }
        long nextLong(){ return Long.parseLong(next()); }
    }

    FastScanner sc;
    PrintWriter out;

    public static void main(String[] args){
        new Main().run();
//        new Thread( null, new Runnable() {
//            @Override
//            public void run() {
//                new Main().run();
//            }
//            }, "LOL", 256L * 1024 * 1024 / 2 ).run();
//        }, "LOL", 2000 * 1024 * 1024 ).run();
    }

    void TLE(){ for(;;); }

    void MLE(){
        int[][] adj = new int[1024*1024][];
        for( int i = 0; i < adj.length; ++i )
            adj[i] = new int[1024*1024];
    }

    void exit( int val ){
        out.flush();
        System.exit(val);
    }
    //////////////////////////////////////////////////////////////////////////////////////////

    int n, m;
    boolean[][] grid;
    ArrayList<Integer>[] gr;
    int c;
    int[] mt;
    boolean[] u;

    boolean try_kuhn( int v ){
        if( u[v] ) return false;
        u[v] = true;
        for( int to : gr[v] ){
            if( to == c ) continue;
            if( mt[to]==-1 || try_kuhn(mt[to]) ){
                mt[to] = v;
                return true;
            }
        }
        return false;
    }

    void solve(){
        n = sc.nextInt();
        m = sc.nextInt();
        grid = new boolean[n+1][n+1];
        gr = new ArrayList[n+1];
        for( int v = 1; v <= n; ++v ) gr[v] = new ArrayList<Integer>();
        for( int it = 0; it < m; ++it ){
            int a = sc.nextInt();
            int b = sc.nextInt();
            grid[a][b] = true;
            gr[a].add(b);
        }

        int ans = Integer.MAX_VALUE;
        for( c = 1; c <= n; ++c ){
            int curAns = 0;
            for( int v = 1; v <= n; ++v )
                if( v != c ){
                    if( !grid[c][v] ) ++curAns;
                    if( !grid[v][c] ) ++curAns;
                }
            if( !grid[c][c] ) ++curAns;

            mt = new int[n+1];
            fill( mt, -1 );
            for( int i = 1; i <= n; ++i )
                if( i != c ){
                    u = new boolean[n+1];
                    try_kuhn(i);
                }

            int szMt = 0;
            for( int i = 1; i <= n; ++i )
                if( mt[i] != -1 )
                    ++szMt;
            curAns += n - 1 - szMt;

            for( int a = 1; a <= n; ++a ){
            for( int b : gr[a] ){
                if( a==c || b==c ) continue;
                if( a!=mt[b] ) ++curAns;
            }
            }

//            out.printf( "%d %d\n", c, curAns );
            ans = min( ans, curAns );
        }
        out.println( ans );
    }

}


import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author sheep
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
    public void solve(int testNumber, InputReader in, PrintWriter out) {
        int n = in.nextInt();
        boolean[][] map = new boolean[n][n];
        int m = in.nextInt();

        int[] us = new int[m];
        int[] vs = new int[m];

        for (int i = 0; i < m; ++i) {
            int u = in.nextInt() - 1;
            int v = in.nextInt() - 1;
            map[u][v] = true;

            us[i] = u;
            vs[i] = v;
        }

        int ans = Integer.MAX_VALUE;
        for (int center = 0; center < n; ++center) {
            int fixed = 0;
            for (int i = 0; i < n; ++i) {
                if (!map[center][i]) {
                    ++fixed;
                }
                if (!map[i][center] && i != center) {
                    ++fixed;
                }
            }

            MaxFlow flow = new MaxFlow(n * 2 + 2, n * 2, n * 2 + 1);

            for (int i = 0; i < n; ++i) {
                if (i == center) continue;
                flow.insert(n * 2, i, 1);
                flow.insert(i + n, n * 2 + 1, 1);
            }

            for (int i = 0; i < m; ++i) {
                if (us[i] == center || vs[i] == center) {
                    continue;
                }

                flow.insert(us[i], vs[i] + n, 1);
                ++fixed;
            }

            ans = Math.min(ans, fixed + (n - 1) - 2 * flow.maxFlow());
        }

        out.println(ans);
    }
}

class InputReader {
    BufferedReader reader;
    StringTokenizer tokenizer;

    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream));
        tokenizer = null;
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (Exception e) {
                throw new UnknownError();
            }
        }
        return tokenizer.nextToken();
    }

    public int nextInt() {
        return Integer.parseInt(next());
    }

    }

class MaxFlow
{
    public class Edge
    {
        public int u,v,c;
        public Edge next,r;

        public Edge(int u,int v,int c)
        {
            this.u = u;
            this.v = v;
            this.c = c;
            next = r = null;
        }
    }

    public Edge vertex[];
    public int height[], nheight[];
    public int s, t, n;

    public void init(int n,int s,int t)
    {
        height = new int[n+1];
        nheight = new int[n+1];
        vertex = new Edge[n+1];
        this.s = s;
        this.t = t;
        this.n = n;
    }

    public MaxFlow(int n,int s,int t)
    {
        init(n,s,t);
    }

    public void insert(int u,int v,int c)
    {
        Edge e = new Edge(u,v,c);
        Edge r = new Edge(v,u,0);
        e.r = r;
        r.r = e;
        e.next = vertex[u];
        vertex[u] = e;
        r.next = vertex[v];
        vertex[v] = r;
    }

    public int augPath(int u,int push)
    {
        if (u == t) return push;
        int flow = push, minheight = n-1;
        for (Edge e = vertex[u]; e != null; e = e.next)
            if (e.c != 0)
            {
                if (height[e.v] + 1 == height[e.u])
                {
                    int delta = flow < e.c ? flow : e.c;
                    if (delta > 0)
                        delta = augPath(e.v,delta);
                    e.c -= delta;
                    e.r.c += delta;
                    flow -= delta;
                    if (0 == flow || height[s] >= n) return push - flow;
                }
                minheight = Math.min(minheight, height[e.v]);
            }
        if (push == flow)
        {
            --nheight[height[u]];
            if (0 == nheight[height[u]]) height[s] = n;
            height[u] = ++minheight;
            ++nheight[height[u]];
        }
        return push - flow;
    }

    public int maxFlow()
    {
        Arrays.fill(height, 0);
        Arrays.fill(nheight, 0);
        nheight[0] = n;
        int flow = 0;
        while (height[s] < n)
            flow += augPath(s,Integer.MAX_VALUE);
        return flow;
    }
}


import com.sun.java_cup.internal.runtime.virtual_parse_stack;

import java.util.Arrays;
import java.util.Scanner;

/**
 * Created by ali on 2/3/14.
 */
public class D
{
	public static void main(String [] args)
	{
		Scanner in = new Scanner(System.in);

		int n = in.nextInt();
		int m = in.nextInt();

		boolean [][] graph = new boolean[n][n];
		for(int i = 0 ; i < m ; i++)
		{
			int a = in.nextInt() - 1;
			int b = in.nextInt() - 1;

			graph[a][b] = true;
		}

		int res = Integer.MAX_VALUE;
		for(int center = 0 ; center < n ; center++)
		{
			int calc = 0;
			for(int i = 0 ; i < n ; i++)
			{
				if(!graph[center][i])
					calc++;
				if(!graph[i][center])
					calc++;
			}

			if(!graph[center][center])
				calc--;

			int [] match = new int[n];
			Arrays.fill(match, -1);
			int max = 0;

			for(int i = 0 ; i < n ; i++)
				if(i != center)
					if(can(i, graph, new boolean[n], center, match))
						max++;

			int unusable = m - (2*n - 1 - calc) - max;
			calc += unusable;
			calc += (2*(n-1) - 2*max)/2;

			res = Math.min(res, calc);
		}

		System.out.println(res);

	}

	private static boolean can(int at, boolean[][] graph, boolean[] visited, int center, int [] match)
	{
		if(visited[at])
			return false;
		visited[at] = true;

		for(int to = 0 ; to < graph.length ; to++)
			if(graph[at][to])
				if(to != center)
					if(match[to] == -1 || can(match[to], graph, visited, center, match))
					{
						match[to] = at;
						return true;
					}

		return false;
	}
}


import java.io.InputStreamReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		FastScanner in = new FastScanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		TaskD solver = new TaskD();
		solver.solve(1, in, out);
		out.close();
	}
}

class TaskD {
        ArrayList<Integer>[] g;
        int n, m;
        boolean[][] have;
        int[] x;
        int[] y;
        boolean[] used;
        int stop;

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
                n = in.nextInt();
                g = new ArrayList[n];
                for (int i = 0; i < n; i++)
                        g[i] = new ArrayList<>();
                have = new boolean[n][n];
                m = in.nextInt();
                for (int i = 0; i < m; i++) {
                        int a = in.nextInt();
                        int b = in.nextInt();
                        --a;
                        --b;
                        g[a].add(b);
                        have[a][b] = true;
                }
                int res = Integer.MAX_VALUE;
                for (int center = 0; center < n; center++)
                        res = Math.min(res, solve(center));
                out.print(res);
        }

        int solve(int v) {
                stop = v;
                int withV = 0;
                int add = 0;
                for (int i = 0; i < n; i++)
                        if (i != v)
                                if (have[v][i])
                                        withV++;
                                else
                                        add++;
                for (int i = 0; i < n; i++)
                        if (i != v)
                                if (have[i][v])
                                        withV++;
                                else
                                        add++;
                if (have[v][v])
                        withV++;
                else
                        add++;
                x = new int[n];
                y = new int[n];
                used = new boolean[n];
                Arrays.fill(x, -1);
                Arrays.fill(y, -1);
                int matched = 0;
                for (int i = 0; i < n; i++)
                        if (i != v && x[i] == -1) {
                                Arrays.fill(used, false);
                                if (dfs(i))
                                        matched++;
                        }
                add += n - 1 - matched;
                add += m - withV - matched;
                return add;
        }

        boolean dfs(int v) {
                if (used[v])
                        return false;
                used[v] = true;
                for (int to : g[v])
                        if (to != stop && y[to] == -1) {
                                x[v] = to;
                                y[to] = v;
                                return true;
                        }
                for (int to : g[v])
                        if (to != stop && dfs(y[to])) {
                                x[v] = to;
                                y[to] = v;
                                return true;
                        }
                return false;
        }
}

class FastScanner {
        BufferedReader reader;
        StringTokenizer tokenizer;

        public FastScanner(InputStream inputStream)  {
                reader = new BufferedReader(new InputStreamReader(inputStream));
        }

        public String nextToken() {
                while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                        String line;
                        try {
                                line = reader.readLine();
                        } catch (IOException e) {
                                return null;
                        }
                        tokenizer = new StringTokenizer(line);
                }
                return tokenizer.nextToken();
        }

        public int nextInt() {
                return Integer.parseInt(nextToken());
        }

        }


import java.util.Scanner;

public class P23A {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		String input = scan.nextLine();
		System.out.println(F(input));
	}

	static int F(String string){
		int ans =0;
		for (int i = 0; i < string.length(); i++) {
			for (int j = 1; j < string.length()-i; j++) {
				String s = string.substring(i, i+j);
				int a=string.indexOf(s);
				int b=string.lastIndexOf(s);
				if ( a >= 0 && b >=0 && a !=b)  ans =Math.max(ans, s.length());
			}
		}
		return ans;
	}
}


import java.util.*;

public class A {

    static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        String s = sc.next();
        for (int l = s.length(); l > 0; --l) {
            HashSet<String> set = new HashSet<String>();
            for (int i = 0; i < s.length() - l + 1; ++i)
                if (set.contains(s.substring(i, i + l))) {
                    System.out.println(l);
                    return;
                } else {
                    set.add(s.substring(i, i + l));
                }
        }
        System.out.println(0);
    }

}


import java.util.Scanner;

public class Prob023A
{
    public static void main( String[] Args )
    {
        Scanner scan = new Scanner( System.in );
        String s = scan.next();

        all: for ( int x = s.length() - 1; x >= 0; x-- )
            for ( int y = 0; x + y <= s.length(); y++ )
            {
                String sub = s.substring( y, y + x );
                if ( s.indexOf( sub, y + 1 ) >= 0 )
                {
                    System.out.println( x );
                    break all;
                }
            }
    }
}


import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class A23 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();
		Map<String, Boolean> map = new HashMap<String, Boolean>();
		for (int i = s.length(); i >= 1; i--) {
			map.clear();
			for (int j = 0; j < s.length()-i+1; j++) {
				String temp = s.substring(j, j+i);
				if (map.containsKey(temp)) {
					System.out.println(i);
					return;
				}
				map.put(temp, true);
			}
		}
		System.out.println(0);
	}

}


/**
 * MxNINJA 04:06:52 ص 14/01/2014
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder line = new StringBuilder(reader.readLine());
        int length = 0;
        for (int head = 0; head < line.length(); head++) {
            for (int tail = line.length() - 1; tail > head; tail--) {
                String subString = line.substring(head, tail);
                if(line.indexOf(subString,head+1)>-1){
                    length = Math.max(subString.length(), length);
                }
            }
        }
        System.out.println(length);
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class YouAreGivenAString {
	public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
		String s=r.readLine();
		int max=0;
		for(int i=1;i<s.length();i++){
			for (int j = 0; j <= s.length()-i; j++) {
				String sub=s.substring(j,j+i);
				if(count(s,sub)>=2)
				max=Math.max(max, i);
			}
		}
		System.out.println(max);
	}

	private static int count(String s, String sub) {
		int l=sub.length();
		int c=0;
		for(int i=0;i<=s.length()-l;i++){
			if(s.substring(i,i+l).equals(sub))
				c++;
		}
		return c;
	}
}


import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner r = new Scanner(System.in);

        String a = r.next();
        char[] c = a.toCharArray();

        for(int l = a.length()-1; l >= 1; l--){
            for(int i = 0; i <= a.length()-l; i++){
                int j = i+l-1;

                for(int s = 0; s <= a.length()-l; s++){
                    if(i == s)continue;
                    if(a.substring(i, i+l).equals(a.subSequence(s, s+l))){
                        System.out.println(l);
                        System.exit(0);
                    }

                }
            }
        }

        System.out.println(0);

    }
}


import java.io.*;
import java.util.*;

public class Main{
	public static void main( String[] args ){
		Scanner cin = new Scanner( System.in );
		String s = cin.next();
		int n = s.length();
		char[] ss = new char[ n ];
		ss = s.toCharArray();

		int ans = 0;

		for (int i=0; i<n; i++)
			for (int j=i+1; j<n; j++){
				int k = 0;
				while ( i+k<n && j+k<n && ss[i+k] == ss[j+k] ) k++;

				ans = Math.max( ans, k );
			}

		System.out.println( ans );
	}
}


import java.util.Scanner;

public class prob1 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String s = input.next();
		int n = s.length();
		int i = n-1;
		CharSequence temp;
		for(i = n-1; i > 0; i--)
			for(int j = 0 ; j <= n-i; j++)
			{
				temp = s.subSequence(j, i+j);
				if( s.substring(j+1, n).contains(temp) || s.substring(0, j+i-1).contains(temp))
				{
					System.out.println(i);
					return;
				}
			}
		System.out.println(0);
	}
}


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.fill;
import static java.util.Arrays.binarySearch;
import static java.util.Arrays.sort;

public class Main {
	public static void main(String[] args) throws IOException {
		try {
			if (new File("input.txt").exists())
				System.setIn(new FileInputStream("input.txt"));
		} catch (SecurityException e) {}

		new Main().run();
	}

	BufferedReader in;
	PrintWriter out;
	StringTokenizer st = new StringTokenizer("");

	void run() throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);

		String s = in.readLine();

		for (int len = s.length() - 1; len > 0; len--) {
			Set<String> set = new HashSet<String>();
			for (int i = 0; i + len <= s.length(); i++) {
				String ss = s.substring(i, i + len);
				if (set.contains(ss)) {
					out.println(len);
					out.close();
					return;
				}
				set.add(ss);
			}
		}
		out.println(0);
		out.close();
	}

	String nextToken() throws IOException {
		while (!st.hasMoreTokens())
			st = new StringTokenizer(in.readLine());
		return st.nextToken();
	}

	int nextInt() throws IOException {
		return Integer.parseInt(nextToken());
	}

	long nextLong() throws IOException {
		return Long.parseLong(nextToken());
	}

	double nextDouble() throws IOException {
		return Double.parseDouble(nextToken());
	}

	String nextLine() throws IOException {
		st = new StringTokenizer("");
		return in.readLine();
	}

	boolean EOF() throws IOException {
		while (!st.hasMoreTokens()) {
			String s = in.readLine();
			if (s == null)
				return true;
			st = new StringTokenizer(s);
		}
		return false;
	}
}


import java.util.*;
import java.io.*;

public class a {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.next();

		int len = s.length();
		for(int i=len-1; i>=1; --i) {
			for(int j=0; j<=len - i; ++j) {
				String ss = s.substring(j, j+i);

				if(s.substring(j+1).indexOf(ss)!=-1) {
					System.out.println(ss.length());
					return;
				}
			}
		}
		System.out.println(0);
	}
}


import java.io.*;
import java.util.*;

public class Main implements Runnable {

	public void _main() throws IOException {
		String s = next();
		for (int len = s.length(); len >= 1; len--) {
			for (int i = 0; i + len <= s.length(); i++)
				for (int j = i + 1; j + len <= s.length(); j++)
					if (s.substring(i, i + len).equals(s.substring(j, j + len))) {
						out.print(len);
						return;
					}
		}
		out.print(0);
	}

	private BufferedReader in;
	private PrintWriter out;
	private StringTokenizer st;

	private String next() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			String rl = in.readLine();
			if (rl == null)
				return null;
			st = new StringTokenizer(rl);
		}
		return st.nextToken();
	}

	private int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	private long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	private double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public static void main(String[] args) {
		new Thread(new Main()).start();
	}

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new PrintWriter(System.out);

			_main();

			out.close();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(202);
		}
	}

}


import java.io.*;
import java.util.*;

public class Main implements Runnable
{
  Scanner in;
  PrintWriter out; //= new PrintWriter(System.out);

  public static void main(String[] args) throws FileNotFoundException, IOException
  {
    new Thread(new Main()).start();
  }

  public class Pair
  {
    public long last;
    public long count;
    public int L;
    Pair(long l, long c) {last = l; count = c;}
    Pair(long l, long c, int L) {last = l; count = c; this.L = L;}
  }

  public void run()
  {
    final String name = "B-small";
    //try {
      in = new Scanner(System.in);// (new File(name + ".in"));//StreamTokenizer(new FileReader(new File(name + ".in")));
      out = new PrintWriter(System.out); // new PrintWriter(new File(name + ".out")); //= new PrintWriter(System.out);
    //} catch (IOException e) {}

    String s = in.next().trim();
    int n = s.length();
    boolean[][] a = new boolean[n][n];

   for (int i = 0; i < n; ++i)
     for (int j = i + 1; j < n; ++j)
       a[i][j] = (s.charAt(i) == s.charAt(j));

    int max = 0;
    for (int i = 0; i < n; ++i)
     for (int j = i + 1; j < n; ++j)
     {
       int k =0;
       while (i + k < n && j + k < n && a[i + k][j + k])
           ++k;

       if (max < k)
           max = k;
     }

    out.println(max);
    out.flush();
  }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;

public class A {
    private BufferedReader in;
    private StringTokenizer st;
    private PrintWriter out;

    private void solve() throws IOException {
        String s = next();
        for (int length = s.length() - 1; length > 0; --length) {
            Set<String> h = new HashSet<String>();
            int count = 0;
            for (int i = 0; i + length <= s.length(); ++i) {
                h.add(s.substring(i, i + length));
                ++count;
            }
            if (count != h.size()) {
                out.println(length);
                return;
            }
        }
        out.println(0);
    }

    public void run() throws IOException {
        in = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);
        eat("");
        solve();
        out.close();
        in.close();
    }

    private void eat(String s) {
        st = new StringTokenizer(s);
    }

    private String next() throws IOException {
        while (!st.hasMoreTokens()) {
            String line = in.readLine();
            if (line == null) {
                return null;
            }
            eat(line);
        }
        return st.nextToken();
    }

    private int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    private long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    private double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }

    private BigInteger nextBigInteger() throws IOException {
        return new BigInteger(next());
    }

    public static void main(String[] args) throws IOException {
        Locale.setDefault(Locale.US);
        new A().run();
    }
}


import java.util.*;
import java.io.*;

public class A0023 {

    public static void main(String args[]) throws Exception {
        new A0023();
    }

    A0023() throws Exception {
        PandaScanner sc = null;
        PrintWriter out = null;
        try {
            sc = new PandaScanner(System.in);
            out = new PrintWriter(System.out);
        } catch (Exception ignored) {
        }

        String s = sc.next();
        int i = s.length() - 1;
        Test: for (; i > 0; i--) {
            HashSet<String> set = new HashSet<String>();
            for (int j = 0; j + i <= s.length(); j++) {
                String ss = s.substring(j, j + i);
                if (set.contains(ss)) {
                    break Test;
                }
                set.add(ss);
            }
        }
        out.println(i);

        out.close();
        System.exit(0);
    }

    //The PandaScanner class, for Panda fast scanning!
    public class PandaScanner {
        BufferedReader br;
        StringTokenizer st;
        InputStream in;

        PandaScanner(InputStream in) throws Exception {
            br = new BufferedReader(new InputStreamReader(this.in = in));
        }

        public String next() throws Exception {
            if (st == null || !st.hasMoreTokens()) {
                st = new StringTokenizer(br.readLine().trim());
                return next();
            }
            return st.nextToken();
        }

        public boolean hasNext() throws Exception {
            return (st != null && st.hasMoreTokens()) || in.available() > 0;
        }

        public long nextLong() throws Exception {
            return Long.parseLong(next());
        }

        public int nextInt() throws Exception {
            return Integer.parseInt(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ProblemA {

	public static void main(String[] args) throws IOException {
		BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
		PrintWriter out = new PrintWriter(System.out);

		String line = s.readLine();
		int len = line.length();
		int max = 0;
		for (int i = 0 ; i < len ; i++) {
			for (int j = i+1 ; j <= len ; j++) {
				String sch = line.substring(i, j);
				for (int k = i+1 ; k + (j - i) <= len ; k++) {
					String tch = line.substring(k, k+(j-i));
					if (sch.equals(tch)) {
						max = Math.max(max, (j-i));
					}
				}
			}
		}
		out.println(max);
		out.flush();
	}

	public static void debug(Object... os){
		System.err.println(Arrays.deepToString(os));
	}
}


import java.io.*;
public class A23 {
    public static void main(String[] args) throws IOException   {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        for(int length = s.length(); length > 0; length--)      {
            for(int start = 0; start + length <= s.length(); start++)       {
                String test = s.substring(start, start+length);
                if(s.indexOf(test) != s.lastIndexOf(test))  {
                    System.out.println(length);
                    return;
                }
            }
        }
        System.out.println(0);
    }
}


//package arbuz;

import java.util.Scanner;

public class Arbuz {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        int i, j, current, longest = 0;
        for (i = 0; i < s.length(); i++) {
            for (j = 0; j < s.length(); j++) {
                if (i != j) {
                    int ti = i, tj = j;
                    current = 0;
                    while (ti < s.length() && tj < s.length() && s.charAt(ti) == s.charAt(tj)) {
                        current++;
                        ti++;
                        tj++;
                    }
                    if (current > longest) {
                        longest = current;
                    }
                }
            }
        }
        System.out.println(longest);
    }
}


// by agus.mw
import java.util.*;
import java.io.*;

public class Main{
  public static void main(String[] args) throws Exception {
    new Main().doWork();
  }
  void doWork() throws Exception{
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

    String text = reader.readLine().trim();
    int out = 0;
    for(int i=0;i<text.length();i++){
      for(int j=i+1;j<text.length();j++){
        for(int len = out+1;len+j<=text.length();len++){
          if(text.substring(i,i+len).compareTo(text.substring(j,j+len))==0){
            out = len;
          }
        }
      }
    }
    String buf = ""+out;
    writer.write(buf,0,buf.length());
    writer.newLine();
    writer.flush();
    writer.close();
    reader.close();
  }
  String process(){
    return "1";
  }
  int[] toIntArray(String line){
    String[] p = line.split("[ ]+");
    int[] out = new int[p.length];
    for(int i=0;i<p.length;i++) out[i] = Integer.valueOf(p[i]);
    return out;
  }
}


import java.util.Scanner;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author madi
 */
public class GivenString {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String line = sc.nextLine();

        String sub = "";
        int count = 0;
        int max = 0;
        for (int i = 0; i < line.length() - 1; i++) {
            sub = line.substring(i, i + 1);

            int q = i + 1;
            int p;
            int r = i;
            while (q < line.length() && q > 0) {
                p = q;
                r = i;
                int ind = line.indexOf(sub, p);
                count = 0;
                if (ind != -1) {
                    for (int j = ind; j < line.length(); j++) {
                        if (line.substring(j, j + 1).equalsIgnoreCase(line.substring(r, r + 1))) {
                            r++;
                            count++;
                        } else {
                            break;
                        }
                    }
                    if (count > max) {
                        max = count;
                    }
                }
                q = ind + 1;

            }

        }

        System.out.println(max);

    }
}


import java.util.*;
import java.io.*;
public class Main {

    static Scanner cin = new Scanner(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter cout = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    public static void main(String[] agrs) throws IOException{

        String line = cin.nextLine();

        HashMap<String, Integer> map = new HashMap<String, Integer>();
        int ans = 0;
        for (int i = 0; i < line.length(); ++i) {
            StringBuffer str = new StringBuffer("");
            for (int j = i; j < line.length(); ++j) {
                str.append(line.charAt(j));

                if (!map.containsKey(str.toString())) {
                    //cout.println(str.toString());
                    map.put(str.toString(), 1);
                } else {
                    ans = str.length() > ans ? str.length() : ans;
                }
            }
        }

        cout.println(ans);

        cin.close();
        cout.close();
    }
}


import java.util.Scanner;

/**
 * @author Alexander Grigoryev
 *         Created on 01.08.11
 */
public
class Main
{
    static Scanner in = new Scanner(System.in);

    public static
    void main(String[] args)
    {
        String s = in.nextLine();
        int k, ans = 0;

        for(int i = 0; i < s.length(); i++)
            for(int j = i + 1; j < s.length(); j++)
            {
                for(k = 0; j + k < s.length(); k++)
                {
                    if(s.charAt(i + k) != s.charAt(j + k)) break;
                }
                if(ans < k) ans = k;
            }
        System.out.println(ans);
    }
}


import java.util.Scanner;

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.next(),c;
        int n = s.length(),a,b;

        for(int sz = n ; sz >= 1 ; sz--) {
            for(int i = 0 ; i+sz <= n ; i++) {
                c = s.substring(i, i+sz);
                a = s.indexOf(c,0);
                if(a < 0) continue;
                b = s.indexOf(c,a+1);
                if(b < 0) continue;
                System.out.println(sz);
                return;

            } // for j
        } // for i
        System.out.println(0);

    }

}


import java.util.Scanner;

public class St {

    static void metod() throws Exception {
        Scanner in = new Scanner(System.in);
        String str = in.next();

        int max = 0;
        for (int i = 0; i < str.length(); i++) {
            for (int j = i + 1; j < str.length() + 1; j++) {

                for (int k = 0; k < str.length(); k++) {
                    for (int n = k + 1; n < str.length() + 1; n++) {

                        if ((str.substring(i, j).equals(str.substring(k, n)))
                                && (k != i)) {
                            if (j - i > max)
                                max = j - i;
                        }
                    }
                }
            }
        }
        System.out.println(max);
    }

    public static void main(String args[]) throws Exception {
        St.metod();
    }
}


import java.util.*;

public class test
{
    static boolean isOK(String str, int len)
    {
	HashSet<String> hs=new HashSet<String>();

	for(int i=0;i<=str.length()-len;i++)
	{
	    String s=str.substring(i,len+i);
	    if(hs.contains(s))
		return true;
	    else
		hs.add(s);
	}

	return false;
    }
    public static void main(String[] args)
    {
        Scanner in=new Scanner(System.in);
        String str=in.next();

        int i;
        for(i=str.length()-1;i>=1;i--)
            if(isOK(str,i))
            {
        	break;
            }

        System.out.println(i);
    }
}


import java.util.*;
import java.io.*;

public class givenstring {
	public static void main(String[] args){
		Scanner reader = new Scanner(System.in);
		String in = reader.next();

		int max = 0;

		for(int i = 0; i < in.length(); i++){
			for(int j = i+1; j < in.length(); j++){
				//take this substring
				String consider = in.substring(i, j);
				for(int k = i+1; k < in.length(); k++){
					if(k + consider.length() > in.length())
						break;
					else if(in.substring(k, k+consider.length()).equals(consider))
						max = Math.max(max, consider.length());
				}
			}
		}

		System.out.println(max);
	}
}


import java.util.*;
import java.lang.*;
import java.math.*;

public class A {

    Scanner sc = new Scanner(System.in);

    void run(){

        String s = sc.next();
        String subS;
        int max = 0;

        for (int i=0;i<s.length();i++) {
            for (int j=i+1;j<s.length()+1;j++) {

                subS = s.substring(i, j);

                for (int k=i+1;k<s.length();k++) {

                    if ( s.startsWith(subS,k) ){
                        if ( max < subS.length() )
                            max = subS.length();
                    }
                }

            }
        }

        System.out.println(max);
        return;

    }

    public static void main(String[] args){

        new A().run();

    }

}


import java.io.*;
import java.util.StringTokenizer;

public class DoubleWord implements Runnable {

    boolean isLocalMode =false;

    private void doJob() throws Exception {
        //do here
        String s = nextToken();
                int max=0;
        for(int i = 0;i<s.length();i++){
            for(int j=i+1;j<s.length()+1;j++){
                String s1 = s.substring(i, j);
                if(s.substring(i+1).contains(s1)){
                    max = Math.max(max,s1.length());
                }
            }
        }
        writer.write(""+max);
    }

    public static void main(String[] args) {
        new DoubleWord().run();
    }

    BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter writer;

    public void run() {
        try {
            reader = new BufferedReader(getReader());
            tokenizer = null;
            writer = new PrintWriter(System.out);
            //do job
            doJob();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    String nextToken() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    public Reader getReader() throws FileNotFoundException {
        if (isLocalMode) {
            return new FileReader("input.txt");
        } else {
            return new InputStreamReader(System.in);
        }
    }
}


import java.util.*;
import java.io.*;
import static java.util.Arrays.*;
import static java.lang.Math.*;
import java.math.*;

public class Main {

    void run() throws IOException {
        String s = token();
        HashSet <String> h;
        int n = s.length();
        int r = 0;
        loop: for (int i = 1; i <= n; i++) {
            h = new HashSet();
            for (int j = 0; j < n - i + 1; j++) {
                String t = s.substring(j, j + i);
                if (h.contains(t)) {
                    r = i;
                    continue loop;
                } else {
                    h.add(t);
                }
            }
        }
        System.out.println(r);
    }

    public static void main(String[] args) throws IOException {
        Locale.setDefault(Locale.US);
        //final String FILENAME = "dvd";
        //in = new BufferedReader(new FileReader(new File(FILENAME + ".in")));
        //out = new PrintWriter(new File(FILENAME + ".out"));
        in = new BufferedReader(new InputStreamReader(System.in));
        //in = new Scanner(System.in);
        out = new PrintWriter(System.out);
        st = new StringTokenizer(" ");
        new Main().run();
        out.close();
    }

    static BufferedReader in;
    //static Scanner in;
    static PrintWriter out;
    static StringTokenizer st;

    String token() throws IOException {
        while (!st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

    int nint() throws IOException {
        return Integer.parseInt(token());
    }

    long nlong() throws IOException {
        return Long.parseLong(token());
    }

    double ndouble() throws IOException {
        return Double.parseDouble(token());
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class A implements Runnable {
    private void solve() throws IOException {
        String str = nextToken();
        for (int i=str.length()-1; i>=0; --i)
            for (int j=0; j+i<=str.length(); ++j)
                if (str.substring(j+1).contains(str.substring(j, j+i))) {
                    writer.println(i);
                    return;
                }
        writer.println(0);
    }

    public static void main(String[] args) {
        new Thread(new A()).start();
    }

    BufferedReader reader;
    StringTokenizer tokenizer;
    PrintWriter writer;

    public void run() {
        try {
            reader = new BufferedReader(new InputStreamReader(System.in));
            tokenizer = null;
            writer = new PrintWriter(System.out);
            solve();
            reader.close();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    String nextToken() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }
}


import java.io.*;
import java.util.*;

public class Main {

	/**
	 * @author hunglee
	 */
	public static void main(String[] args) throws IOException {

		StreamTokenizer in = new StreamTokenizer(new BufferedReader(
				new InputStreamReader(System.in)));

		in.nextToken();
		String s = in.sval;
		int l = s.length();
		int n = l - 1;
		String st, sub;
		while (n > 0) {
			for (int i = 0; i < l - n; ++i) {
				st = s.substring(i, n + i);
				sub = s.substring(i + 1);
				if (sub.indexOf(st) != -1) {
					System.out.println(n);
					System.exit(0);
				}
			}
			n--;
		}
		System.out.println(0);
	}

}


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class OverlapedString {
	public static void main(String args[]) throws Exception {
		OverlapedString os = new OverlapedString();
		BufferedReader stdin =
			new BufferedReader(new InputStreamReader(System.in));
		String line;
		while ((line = stdin.readLine()) != null) {
			System.out.println(os.handleOverlap(line));
		}
	}
	private int handleOverlap(String str) {
		int len = str.length();
		int count = 0;
		for(int i=0;i<len;i++)
			for(int j=i+1;j<len;j++) {
				String _tmp = str.substring(i,j);
				if(_tmp!=null&&_tmp.length()>0) {
					if(getOverlapCount(str,_tmp)>1)
					{
						if(_tmp.length()>count)
							count = _tmp.length();
					}
				}
			}
		return count;
	}
	private int getOverlapCount(String str,String sub) {
		int start = 0;
		int count = 0;
		while(start<str.length()) {
			start = str.indexOf(sub,start);
			if(start==-1)
				break;
			else {
				start++;
				count++;
			}
		}
		return count;
	}
}


import java.io.*;
import java.util.*;

public class A
{
	String line;
	StringTokenizer inputParser;
	BufferedReader is;
	FileInputStream fstream;
	DataInputStream in;

	void openInput(String file)
	{

		if(file==null)is = new BufferedReader(new InputStreamReader(System.in));//stdin
		else
		{
			try{

			fstream = new FileInputStream(file);
			in = new DataInputStream(fstream);
			is = new BufferedReader(new InputStreamReader(in));
			}catch(Exception e)
			{
				System.err.println(e);
			}
		}

	}

	void readNextLine()
	{
		try {
			line = is.readLine();
			inputParser = new StringTokenizer(line, " ");
			//System.err.println("Input: " + line);
		} catch (IOException e) {
			System.err.println("Unexpected IO ERROR: " + e);
		}

	}

	int NextInt()
	{
		String n = inputParser.nextToken();
		int val = Integer.parseInt(n);

		//System.out.println("I read this number: " + val);
		return val;
	}

	String NextString()
	{
		String n = inputParser.nextToken();
		return n;
	}

	void closeInput()
	{
		try {
			is.close();
		} catch (IOException e) {
			System.err.println("Unexpected IO ERROR: " + e);
		}

	}

	public static void main(String [] argv)
	{
		String filePath=null;
		if(argv.length>0)filePath=argv[0];
		A a = new A(filePath);
	}

	public A(String inputFile)
	{
		openInput(inputFile);

		readNextLine();
		String s=line;
		int ret=0;
		for(int i=0; i<s.length(); i++)
		{
			for(int j=i+1; j<s.length()+1; j++)
			{
				String a=s.substring(i,	j);
				if(s.indexOf(a, i+1)>-1)ret=Math.max(ret, a.length());

			}
		}
		System.out.println(ret);
	}

}


import java.io.IOException;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class A {

    public static void main(String[] args) throws IOException{
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        int n = s.length();
        for (int i = n; i >= 1; i--) {
            Set<String> set = new HashSet<String>();
            for (int j = 0; j < n-i+1; j++) {
                String t = s.substring(j, j+i);
                if (set.contains(t)) {
                    System.out.println(i);
                    return;
                }
                set.add(t);
            }
        }
        System.out.println(0);
    }

}


import java.util.*;

public class A
{
   public static void main(String[] args)
   {
      new A(new Scanner(System.in));
   }

   public A(Scanner in)
   {
      TreeSet<String> ts = new TreeSet<String>();
      ArrayList<String> sr = new ArrayList<String>();

      String s = in.next();
      for (int i=0; i<s.length(); i++)
      {
         for (int j=i+1; j<=s.length(); j++)
         {
            String ss = s.substring(i, j);
            if (ts.contains(ss))
            {
               sr.add(ss);
            }
            ts.add(ss);
         }
      }

      int res = 0;
      for (String ss : sr)
      {
         if (ss.length() > res)
            res = ss.length();
      }

      System.out.printf("%d%n", res);
   }
}


import java.util.*;

public class A {

    static Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        String s = sc.next();
        for (int l = s.length(); l > 0; --l) {
            HashSet<String> set = new HashSet<String>();
            for (int i = 0; i < s.length() - l + 1; ++i)
                if (set.contains(s.substring(i, i + l))) {
                    System.out.println(l);
                    return;
                } else {
                    set.add(s.substring(i, i + l));
                }
        }
        System.out.println(0);
    }

}


import java.io.BufferedReader;
import java.io.InputStreamReader;

public class YouAreGivenAString {

    void run() {
        try {
            BufferedReader bfd = new BufferedReader(new InputStreamReader(
                    System.in));
            int i, j, k, mxLen = 0;
            String s= bfd.readLine();
            for(i=0; i<s.length(); ++i){
                for(j=i+1; j<s.length()+1; ++j){
                    String s2 = s.substring(i, j);
                    if(s2.length()<=mxLen) continue;
                    int cnt=0;
                    for(k=0; k<s.length(); ++k){
                        if(s.length()>=k+s2.length())
                        if(s2.equals(s.substring(k,k+s2.length()))){
                            cnt++;
                            if(cnt>1)mxLen = Math.max(mxLen, s2.length());
                        }
                    }
                }
            }
            System.out.println(mxLen);
        } catch (Exception e) {

        }
    }
    public static void main(String[] args) {
        new YouAreGivenAString().run();
    }

}


import java.util.Scanner;

public class Word {
    static String word;

    private static void check(String subword) {
        int i = 0;
        int j = 0;
        while (j + subword.length() <= word.length()) {
            if (word.substring(j).startsWith(subword)){
                i++;
            }
            j++;
        }
        if (i > 1){
            System.out.println(subword.length());
            System.exit(0);
        }
    }

    public static void main(String[] arg) {
        Scanner in = new Scanner(System.in);
        word = in.next();
        if (word.length() == 1) {
            System.out.println(0);
            return;
        }
        for (int i = word.length() - 1; i > 0; i--) {
            int j = 0;
            while (j + i <= word.length()) {
                check(word.substring(j, i+j));
                j++;
            }
        }
        System.out.println(0);
    }
}


import java.io.*;
import java.util.*;

public class YoureGivenAString {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        String str = f.readLine();
        int max = 0;
        for (int i = 0; i < str.length(); i++)
            for (int j = i+1; j <= str.length(); j++) {
                String s = str.substring(i,j);
                if (str.indexOf(s) >= 0 && str.substring(str.indexOf(s)+1).indexOf(s) >= 0)
                    max = Math.max(max, j-i);
            }
        System.out.println(max);
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * User: alms
 * Date: 09.07.2010
 * Time: 18:57:44
 */
public class Solution {
    public static void main(String[] args) throws Exception {
        final String str;
        final BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
        str = r.readLine();

        int max = 0;

        for (int x = 0; x  < str.length(); x++) {
            for (int y = x + 1; y  < str.length(); y++) {
                int c = 0;
                for (;c + x < str.length() && y + c < str.length(); c++) {
                    if (str.charAt(x + c) != str.charAt(y + c)) {
                        break;
                    }
                }

                if (c > max) {
                    max = c;
                }
            }
        }

        System.out.println(max);
    }
}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
import java.util.TreeSet;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Trung Pham
 */
public class A {

    public static void main(String[] args) throws FileNotFoundException, IOException {
        Scanner in = new Scanner();
        PrintWriter out = new PrintWriter(System.out);
        String val = in.next();
        ArrayList<String> list = new ArrayList();
        for(int i = 0; i < val.length() ; i++){
            list.add(val.substring(i));
        }
        Collections.sort(list);
        int result = 0;
        for(int i = 1; i < list.size() ; i++){
            String other = list.get(i - 1);
            int temp = 0;
            for(int j = 0; j < list.get(i).length() && j < other.length() ; j++){
                if(other.charAt(j) == list.get(i).charAt(j)){
                    temp++;
                }else{
                    break;
                }
            }
            if(temp > result){
                result = temp;
            }
        }
        out.println(result);
        out.close();
    }

    public static int dist(int x0, int y0, int x1, int y1) {
        return (x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1);
    }

    public static boolean isRight(int a, int b, int c) {
        if (a == 0 || b == 0 || c == 0) {
            return false;
        }
        if (a == b + c) {
            return true;
        }
        if (b == a + c) {
            return true;
        }
        if (c == a + b) {
            return true;
        }
        return false;
    }

    public static int gcd(int a, int b) {
        if (b == 0) {
            return a;
        }
        return gcd(b, a % b);
    }

    static class FT {

        int[] data;

        FT(int n) {
            data = new int[n];
        }

        void update(int index, int val) {
            // System.out.println("UPDATE INDEX " + index);
            while (index < data.length) {
                data[index] += val;
                index += index & (-index);

                //    System.out.println("NEXT " +index);
            }
        }

        int get(int index) {
            //  System.out.println("GET INDEX " + index);
            int result = 0;
            while (index > 0) {
                result += data[index];
                index -= index & (-index);
                // System.out.println("BACK " + index);
            }
            return result;
        }
    }

    static int pow(int a, int b) {
        if (b == 0) {
            return 1;
        }
        if (b == 1) {
            return a;
        }
        int val = pow(a, b / 2);
        if (b % 2 == 0) {

            return val * val;
        } else {
            return val * val * a;
        }
    }

//    static Point intersect(Point a, Point b, Point c) {
//        double D = cross(a, b);
//        if (D != 0) {
//            return new Point(cross(c, b) / D, cross(a, c) / D);
//        }
//        return null;
//    }
//
//    static Point convert(Point a, double angle) {
//        double x = a.x * cos(angle) - a.y * sin(angle);
//        double y = a.x * sin(angle) + a.y * cos(angle);
//        return new Point(x, y);
//    }
    static Point minus(Point a, Point b) {
        return new Point(a.x - b.x, a.y - b.y);
    }

    static Point add(Point a, Point b) {
        return new Point(a.x + b.x, a.y + b.y);
    }

    static double cross(Point a, Point b) {
        return a.x * b.y - a.y * b.x;
    }

    static class Point {

        int x, y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "Point: " + x + " " + y;
        }
    }

    static class Scanner {

        BufferedReader br;
        StringTokenizer st;

        public Scanner() throws FileNotFoundException {
            //System.setOut(new PrintStream(new BufferedOutputStream(System.out), true));
            //   br = new BufferedReader(new FileReader("input.txt"));
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        public String next() {

            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (Exception e) {
                    throw new RuntimeException();
                }
            }
            return st.nextToken();
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public String nextLine() {
            st = null;
            try {
                return br.readLine();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }

        public boolean endLine() {
            try {
                String next = br.readLine();
                while (next != null && next.trim().isEmpty()) {
                    next = br.readLine();
                }
                if (next == null) {
                    return true;
                }
                st = new StringTokenizer(next);
                return st.hasMoreTokens();
            } catch (Exception e) {
                throw new RuntimeException();
            }
        }
    }
}


import java.io.InputStream;
import java.io.OutputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.Random;
import java.util.StringTokenizer;

public class Task {

	private static final boolean readFromFile = false;

	public static void main(String args[]){
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		FileOutputStream fileOutputStream;
		FileInputStream fileInputStream;
		if (readFromFile){
			try{
				fileInputStream = new FileInputStream(new File("input.txt"));
				fileOutputStream = new FileOutputStream(new File("output.txt"));
			}catch (FileNotFoundException e){
				throw new RuntimeException(e);
			}
		}
		PrintWriter out = new PrintWriter((readFromFile)?fileOutputStream:outputStream);
		InputReader in = new InputReader((readFromFile)?fileInputStream:inputStream);

		Solver s = new Solver(in,out);
		s.solve();

		out.close();
	}
}

class Solver{
	InputReader in;
	PrintWriter out;

	public void solve(){
		String s = in.nextLine();
		for (int len=s.length()-1;len>=1;len--)
			for (int i=0;i<s.length()-len+1;i++)
				for (int j=i+1;j<s.length()-len+1;j++)
					if (s.substring(i,i+len).equals(s.substring(j,j+len))){
						out.println(len);
						return;
					}
		out.println(0);
	}

	Solver(InputReader in, PrintWriter out){
		this.in=in;
		this.out=out;
	}
}

class InputReader{
	private BufferedReader buf;
	private StringTokenizer tok;

	InputReader(InputStream in){
		tok = null;
		buf = new BufferedReader(new InputStreamReader(in));
	}

	InputReader(FileInputStream in){
		tok = null;
		buf = new BufferedReader(new InputStreamReader(in));
	}

	public String next(){
		while (tok==null || !tok.hasMoreTokens()){
			try{
				tok = new StringTokenizer(buf.readLine());
			}catch (IOException e){
				throw new RuntimeException(e);
			}
		}
		return tok.nextToken();
	}

	public int nextInt(){
		return Integer.parseInt(next());
	}

	public long nextLong(){
		return Long.parseLong(next());
	}

	public double nextDouble(){
		return Double.parseDouble(next());
	}

	public float nextFloat(){
		return Float.parseFloat(next());
	}

	public String nextLine(){
		try{
			return buf.readLine();
		}catch (IOException e){
			return null;
		}
	}

}


import java.util.*;
import java.io.*;
public class Main {
    static BufferedReader reader
        = new BufferedReader(new InputStreamReader(System.in));
    static StringBuilder out = new StringBuilder();

    public static void main(String[] args){
        solve();
        return;
    }

    // the followings are methods to take care of inputs.
    static int nextInt(){
        return Integer.parseInt(nextLine());
    }
    static long nextLong(){
        return Long.parseLong(nextLine());
    }
    static int[] nextIntArray(){
        String[] inp = nextLine().split("\\s+");
        int[] ary = new int[inp.length];
        for (int i = 0; i < ary.length; i++){
            ary[i] = Integer.parseInt(inp[i]);
        }
        return ary;
    }
    static int[] nextIntArrayFrom1(){
        String[] inp = nextLine().split("\\s+");
        int[] ary = new int[inp.length + 1];
        for (int i = 0; i < inp.length; i++){
            ary[i+1] = Integer.parseInt(inp[i]);
        }
        return ary;
    }
    static long[] nextLongArray(){
        String[] inp = nextLine().split("\\s+");
        long[] ary = new long[inp.length];
        for (int i = 0; i < inp.length; i++){
            ary[i] = Long.parseLong(inp[i]);
        }
        return ary;
    }
    static long[] nextLongArrayFrom1(){
        String[] inp = nextLine().split("\\s+");
        long[] ary = new long[inp.length + 1];
        for (int i = 0; i < inp.length; i++){
            ary[i+1] = Long.parseLong(inp[i]);
        }
        return ary;
    }
    static String nextLine(){
        try {
            return reader.readLine().trim();
        } catch (Exception e){}
        return null;
    }
    static void solve(){
        String str = nextLine();
        int max=0;
        int index=0;
        for(int i=0;i<str.length();i++){
            for(int j=i+1;j<str.length();j++){
                if(str.charAt(i)==str.charAt(j)){
                    int count=1;
                    while(true){
                        if(str.length()<=i+count || str.length()<=j+count || str.charAt(i+count)!=str.charAt(j+count) )
                            break;
                        count++;
                    }
                    if(max<count){
                        max=count;
                        index=i;
                    }
                }
            }
        }
        System.out.println(max);

        return;
    }
}


import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.TreeSet;
import java.util.StringTokenizer;
import java.util.AbstractCollection;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Zyflair Griffane
 */
public class Main {
	public static void main(String[] args) {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		PandaScanner in = new PandaScanner(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		A solver = new A();
		solver.solve(1, in, out);
		out.close();
	}
}

class A {
    public void solve(int testNumber, PandaScanner in, PrintWriter out) {
        String s = in.next();
        String[] ss = Substring.allSubstrings(s);
        int res = 0;
        for (String sss: ss) {
            if (sss.length() <= res) continue;
            if (Substring.occurences(s, sss).length > 1) {
                res = sss.length();
            }
        }
        out.println(res);
    }
}

class PandaScanner {
    public BufferedReader br;
    public StringTokenizer st;
    public InputStream in;

    public PandaScanner(InputStream in) {
        br = new BufferedReader(new InputStreamReader(this.in = in));
    }

    public String nextLine() {
        try {
            return br.readLine();
        }
        catch (Exception e) {
            return null;
        }
    }

    public String next() {
        if (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(nextLine().trim());
            return next();
        }
        return st.nextToken();
    }

    }

class Substring {

    public static String[] allSubstrings(String s) {
        TreeSet<String> substrings = new TreeSet<String>();
        int n = s.length();
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                substrings.add(s.substring(i, j));
            }
        }
        return substrings.toArray(new String[0]);
    }

    public static int[] occurences(String s, String target) {
        int n = s.length();
        ArrayList<Integer> res = new ArrayList<Integer>();
        int idx = s.indexOf(target);
        while (idx != -1) {
            res.add(idx);
            if (idx == n - 1) break;
            idx = s.indexOf(target, idx + 1);
        }
        n = res.size();
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
            arr[i] = res.get(i);
        }
        return arr;
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class A {
	private static StreamTokenizer in;
	private static PrintWriter out;

	private static int nextInt() throws Exception {
		in.nextToken();
		return (int) in.nval;
	}

	private static String nextString() throws Exception {
		in.nextToken();
		return in.sval;
	}

	public static void main(String[] args) throws Exception {
		in = new StreamTokenizer(new BufferedReader(new InputStreamReader(
				System.in)));
		out = new PrintWriter(System.out);

		String s = nextString();
		int max = 0;
		for (int i=0; i<s.length(); i++) {
			for (int j=i+1; j<=s.length(); j++) {
//				System.out.println(i+ " "+ j);
				String u = s.substring(i,j);
				if (s.substring(i+1).indexOf(u) >= 0) {
					max = Math.max(max, u.length());
				}
			}
		}
		out.println(max);

		out.flush();
	}
}


import java.util.*;
import java.io.*;

public class P1 {
	public static void main(String[] args) {
		String s = null;
		// citire
		try {
//			Scanner sc = new Scanner(new File("in.txt"));
			Scanner sc = new Scanner(System.in);
			s = sc.next();

		}
		catch (Exception e) {
			e.printStackTrace();
		}

		int n = s.length();

		HashSet<String> h = new HashSet<String>();
		String t=null;
		boolean b;
		int lmax = 0;
		for (int i=0; i<n; i++) {
			for (int j=i+1; j<=n; j++) {
				t = s.substring(i, j);
				b = h.add(t);
//				System.out.println(t + "	"  + b);
				if (b==false) {
					if (j-i>lmax) {
						lmax = j-i;
//						System.out.println(t);
					}
				}
			}
		}
		System.out.println(lmax);
	}
}


import java.io.*;
import java.util.*;
import java.math.*;

public class Main {
    public static void main(String ...args) throws Throwable {
        Scanner in = new Scanner(System.in);
        String init = in.nextLine();
        HashSet<String> h = new HashSet<String>();
        for (int len = init.length() - 1; len >= 1; --len)  {
            h.clear();
            for (int pos = 0; pos + len <= init.length(); ++pos) {
                String now = init.substring(pos, pos + len);
                if (h.contains(now)) {
                    System.out.println(len);
                    return;
                }
                h.add(now);
            }

        }

        System.out.println(0);
    }
}


import java.io.*;

/*************************************************************************
 *  Compilation:  javac LRS.java
 *  Execution:    java LRS < file.txt
 *  Dependencies: StdIn.java
 *
 *  Reads a text corpus from stdin, replaces all consecutive blocks of
 *  whitespace with a single space, and then computes the longest
 *  repeated substring in that corpus. Suffix sorts the corpus using
 *  the system sort, then finds the longest repeated substring among
 *  consecutive suffixes in the sorted order.
 *
 *  % java LRS < mobydick.txt
 *  ',- Such a funny, sporty, gamy, jesty, joky, hoky-poky lad, is the Ocean, oh! Th'
 *
 *  % java LRS
 *  aaaaaaaaa
 *  'aaaaaaaa'
 *
 *  % java LRS
 *  abcdefg
 *  ''
 *
 *************************************************************************/

import java.util.Arrays;

public class LRS {

    // return the longest common prefix of s and t
    public static String lcp(String s, String t) {
        int n = Math.min(s.length(), t.length());
        for (int i = 0; i < n; i++) {
            if (s.charAt(i) != t.charAt(i))
                return s.substring(0, i);
        }
        return s.substring(0, n);
    }

    // return the longest repeated string in s
    public static String lrs(String s) {

        // form the N suffixes
        int N  = s.length();
        String[] suffixes = new String[N];
        for (int i = 0; i < N; i++) {
            suffixes[i] = s.substring(i, N);
        }

        // sort them
        Arrays.sort(suffixes);

        // find longest repeated substring by comparing adjacent sorted suffixes
        String lrs = "";
        for (int i = 0; i < N - 1; i++) {
            String x = lcp(suffixes[i], suffixes[i+1]);
            if (x.length() > lrs.length())
                lrs = x;
        }
        return lrs;
    }

    // read in text, replacing all consecutive whitespace with a single space
    // then compute longest repeated substring
    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String s = br.readLine();
        s = s.replaceAll("\\s+", " ");
        System.out.println(lrs(s).length());
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.util.StringTokenizer;
import java.io.InputStreamReader;

public class Main{
    public static void main(String[] args)throws IOException{
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String s=br.readLine();
        int max=0;
        for(int i=0;i<s.length();i++){
            int len=0;
            int k=i;
            boolean flag=false;
            for(int j=i+1;j<s.length();j++){
                if(s.charAt(k)==s.charAt(j)){
                len++;
                k++;
                flag=true;
                }
                else if(flag==true){
                    j=j-len;
                    k=i;
                    if(max<len)
                    max=len;
                    len=0;
                    flag=false;

                }

            }
            if(max<len)
            max=len;
        }
        System.out.print(max);
    }}


import java.util.*;
public class substring
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String s = input.nextLine();
Boolean found = false;
int i = s.length();
while(found==false)
{
i--;
ArrayList<String> sub = new ArrayList<String>();
for(int j = 0; j <= s.length() - i; j++)
{
if(sub.contains(s.substring(j, j+i)))
found = true;
else
sub.add(s.substring(j, j+i));
}

}
System.out.println(i);
}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;

public class Main20 {

    static ArrayList<Integer> primes = new ArrayList<Integer>();
    static boolean[] prime = new boolean[1001];
    public static void gen(){
        Arrays.fill(prime, true);
        prime[0] = prime[1]  = false;
        for (int i = 2; i < 1001; i++) {
            if (prime[i]){
                primes.add(i);
                for (int j = i*2; j < 1001; j+=i)
                    prime[j] = false;
            }
        }
    }
    public static boolean isVowel(char c){
        Character r = Character.toLowerCase(c);
        return (r == 'e' || r == 'a' || r == 'i' || r == 'o' ||  r == 'u'||  r == 'y');
    }
    public static void main(String[] args) throws IOException {
        Scanner s = new Scanner(new InputStreamReader(System.in));
        String str = s.next();
        int x;
        int max= 0;

        for (int i = 0; i < str.length()-1; i++) {
            for (int j = i+1; j < str.length(); j++) {
                x = str.indexOf(str.substring(i,j),i+1) ;
                if (x != -1){
                    if (j-i > max) max = j-i;
                }
            }
        }
        System.out.println(max);
    }

}


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

//package substring;
import java.util.*;

/**
 *
 * @author lav
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Scanner scr = new Scanner(System.in);
       // System.out.println("entet strig");
        String str = scr.nextLine();
        int len =0;
      //  System.out.println(str.substring(0, str.length()));
        for(int i=0;i<(str.length()-1);i++)
        {
            for(int j=i+1;j<str.length();j++)
            {
                String sub = str.substring(i, j);
                //int a=i+sub.indexOf(sub.charAt(0));
                int ind = str.indexOf(sub, i+1);
                if(ind!=-1 && sub.length()>len )
                {
                    len = sub.length();
                }
            }
        }
        System.out.println(len);
        // TODO code application logic here
    }

}


import java.util.Scanner;

public class P23A {

	public static void main(String[] args) {

		Scanner in = new Scanner(System.in);
		String s = in.nextLine();
		int max = 0;
		for(int i = 0; i < s.length(); i++)
			for(int k = s.length(); k > max + i; k--)
				if(s.substring(i + 1).contains(s.substring(i,k)))
					max = k - i;
		System.out.println(max);
	}

}


//package timus;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.io.Writer;
import java.math.BigInteger;
import java.util.Arrays;

public class Abra {
    public static void main(String[] args) throws IOException {
        new Abra().run();
    }

    StreamTokenizer in;
    PrintWriter out;
    boolean oj;

    void init() throws IOException {
        oj = System.getProperty("ONLINE_JUDGE") != null;
        Reader reader = oj ? new InputStreamReader(System.in) : new FileReader(
                "input.txt");
        Writer writer = oj ? new OutputStreamWriter(System.out)
                : new FileWriter("output.txt");
        in = new StreamTokenizer(new BufferedReader(reader));
        out = new PrintWriter(writer);
    }

    void run() throws IOException {
        long beginTime = System.currentTimeMillis();
        init();
        solve();
        out.flush();
    }

    void printMem() {
        if (!oj) {
            System.out.println("Memory used = "
                    + (Runtime.getRuntime().totalMemory() - Runtime
                            .getRuntime().freeMemory()));
        }
    }

    int nextInt() throws IOException {
        in.nextToken();
        return (int) in.nval;
    }

    long nextLong() throws IOException {
        in.nextToken();
        return (long) in.nval;
    }

    String nextString() throws IOException {
        in.nextToken();
        return in.sval;
    }

    double nextDouble() throws IOException {
        in.nextToken();
        return in.nval;
    }

    long deg(long x, long y) {
        long a = x;
        for (long i = 2; i <= y; i++) {
            a *= x;
        }
        return a;
    }

    long fact(long x) {
        long a = 1;
        for (long i = 2; i <= x; i++) {
            a *= i;
        }
        return a;
    }

    long digitSum(String x) {
        long a = 0;
        for (int i = 0; i < x.length(); i++) {
            a += x.codePointAt(i) - 48;
        }
        return a;
    }

    long digitSum(long x) {
        long a = 0;
        while (x > 0) {
            a += x % 10;
            x /= 10;
        }
        return a;
    }

    long digitMul(long x) {
        long a = 1;
        while (x > 0) {
            a *= x % 10;
            x /= 10;
        }
        return a;
    }

    int digitCubesSum(int x) {
        int a = 0;
        while (x > 0) {
            a += (x % 10) * (x % 10) * (x % 10);
            x /= 10;
        }
        return a;
    }

    double pif(double ax, double ay, double bx, double by) {
        return Math.sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
    }

    double getPosPart(double x) {
        if (x <= 0)
            return 0;
        else
            return x;
    }

    double max(double x, double y) {
        if (x > y)
            return x;
        else
            return y;
    }

    long gcd(long a, long b) {
        if (a < b) {
            long c = b;
            b = a;
            a = c;
        }
        while (a % b != 0) {
            a = a % b;
            if (a < b) {
                long c = b;
                b = a;
                a = c;
            }
        }
        return b;
    }

    int gcd(int a, int b) {
        if (a < b) {
            int c = b;
            b = a;
            a = c;
        }
        while (a % b != 0) {
            a = a % b;
            if (a < b) {
                int c = b;
                b = a;
                a = c;
            }
        }
        return b;
    }

    long lcm(long a, long b) throws IOException {
        return a * b / gcd(a, b);
    }

    int lcm(int a, int b) throws IOException {
        return a * b / gcd(a, b);
    }

    int countOccurences(String x, String y) {
        int a = 0, i = 0;
        while (true) {
            i = y.indexOf(x);
            if (i == -1)
                break;
            a++;
            y = y.substring(i + 1);
        }
        return a;
    }

    int[] primes;

    int findPrimes(int x) {
        boolean[] forErato = new boolean[x];
        primes = new int[x];
        int l = 0, j = 0;
        for (int i = 2; i < x; i++) {
            if (forErato[i])
                continue;
            l++;
            primes[l] = i;
            j = i * 2;
            while (j < x) {
                forErato[j] = true;
                j += i;
            }
        }
        return l;
    }

    int rev(int x) {
        int a = 0;
        while (x > 0) {
            a = a * 10 + x % 10;
            x /= 10;
        }
        return a;
    }

    class myDate {
        int d, m, y;

        public myDate(int da, int ma, int ya) {
            d = da;
            m = ma;
            y = ya;
        }

        int[] ml = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

        void inc() {
            if ((d == 31) && (m == 12)) {
                y++;
                d = 1;
                m = 1;
            } else {
                if (((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0)) {
                    ml[1] = 29;
                }
                if (d == ml[m - 1]) {
                    m++;
                    d = 1;
                } else
                    d++;
            }
        }
    }

    int partition(int n, int l, int m) {// n - sum, l - length, m - every part
        // <= m
        if (n < l)
            return 0;
        if (n < l + 2)
            return 1;
        if (l == 1)
            return 1;
        int c = 0;
        for (int i = Math.min(n - l + 1, m); i >= (n + l - 1) / l; i--) {
            c += partition(n - i, l - 1, i);
        }
        return c;
    }

    String s;
    int l;

    void solve() throws IOException {
        s = nextString();
        l = s.length();
        int max = 0;
        for (int i = 0; i < l - 1; i++) {
            for (int j = i + 1; j < l; j++) {
                if (countOccurences(s.substring(i, j), s) > 1)
                    if (j - i > max) max = j - i;
            }
        }
        out.println(max);
    }
}


import java.util.*;

public class a{
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		String str = in.next();
		int max = 0;
		for(int i=0; i<str.length(); i++) {
			for(int j=i+1; j<=str.length(); j++) {
				String first = str.substring(i,j);
				for(int k=i+1; k<=str.length()-first.length(); k++) {
					if(str.substring(k,k+first.length()).equals(first))
						max = Math.max(max,first.length());
				}
			}
		}
		System.out.println(max);
	}
}


import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Scanner;

public class Main implements Runnable {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new Thread(new Main()).start();
	}

	public void run() {
		Locale.setDefault(Locale.US);
		try {
			run1();
		} catch (IOException e) {
			throw new RuntimeException();
		}
	}

	int nextInt(StreamTokenizer st) throws IOException {
		st.nextToken();
		return (int) st.nval;
	}

	private List<Integer> kmp(String x, String a) {
		String s = a + "$" + x;
		int[] oppa = new int[s.length()];
		oppa[0] = 0;
		int tmp = 0;
		List<Integer> res = new ArrayList<Integer>();
		for (int i = 1; i < s.length(); i++) {
			while (tmp != 0 && s.charAt(tmp) != s.charAt(i)) {
				// System.out.println(i + " " + tmp);
				tmp = oppa[tmp - 1];
			}
			if (s.charAt(tmp) == s.charAt(i))
				tmp++;
			oppa[i] = tmp;
			if (tmp == a.length()) {
				res.add(i - a.length() - a.length());
			}
		}
		return res;
	}

	double nextDouble(StreamTokenizer st) throws IOException {
		st.nextToken();
		return st.nval;
	}

	String nextLine(StreamTokenizer st) throws IOException {
		st.nextToken();
		return st.sval;
	}

	int cnt = 0;
	int[] col;

	void unite(int a, int b) {
		if (cnt % 2 == 0)
			col[getCol(a)] = getCol(b);
		else
			col[getCol(b)] = getCol(a);
		cnt++;
	}

	int getCol(int a) {
		return a == col[a] ? a : (col[a] = getCol(col[a]));
	}

	public void run1() throws IOException {
//		 Scanner sc = new Scanner(new FileReader("input.txt"));
		Scanner sc = new Scanner(new InputStreamReader(System.in));
		// BufferedReader br = new BufferedReader(new
		// InputStreamReader(System.in));
		// PrintWriter pw = new PrintWriter(new FileWriter("output.txt"));
		String s= sc.next();
		int res = 0;
		int n = s.length();
		for(int i = 0; i < n; i++)
			for(int j = i + 1; j < n; j++) {
				int k = 0;
				while(j + k < n && s.charAt(i + k) == s.charAt(j + k))
					k++;
					res = Math.max(res, k);
			}
		System.out.println(res);
	}
}