Go: ///
// File:  0528.go
// Author: ymiyamoto
//
// Created on Thu Mar 22 01:52:09 2018
//
package main

import (
	"bufio"
	"fmt"
	"os"
)

var S, T string
var dp [4001][4001]int

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	for {
		scanner.Scan()
		S = scanner.Text()
		if len(S) == 0 {
			return
		}

		scanner.Scan()
		T = scanner.Text()

		for i := range dp {
			for j := range dp[i] {
				dp[i][j] = 0
			}
		}

		dp[0][0] = 0
		for i := range S {
			for j := range T {
				if S[i] == T[j] {
					dp[i+1][j+1] = max(dp[i+1][j], max(dp[i][j+1], dp[i][j]+1))
				} else {
					dp[i+1][j+1] = 0
				}
			}
		}
		var m int
		for i := range dp {
			for j := range dp[i] {
				m = max(m, dp[i][j])
			}
		}
		fmt.Println(m)
	}
}

C++: #include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<queue>
#include<cstdio>
#include<climits>
#include<cmath>
#include<cstring>
#include<string>
#include<sstream>
#include<numeric>
#include<cassert>

#define f first
#define s second
#define mp make_pair

#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define FOR(i,c) for(__typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define ALL(c) (c).begin(), (c).end()
#define IN(x,s,g) ((x) >= (s) && (x) < (g))
#define ISIN(x,y,w,h) (IN((x),0,(w)) && IN((y),0,(h)))
#define print(x) printf("%d\n",x);

using namespace std;

typedef unsigned int uint;
typedef long long ll;

const int _dx[] = {0,1,0,-1};
const int _dy[] = {-1,0,1,0};

int getInt(){
  int ret = 0,c;
  c = getchar();
  while(!isdigit(c)) c = getchar();
  while(isdigit(c)){
    ret *= 10;
    ret += c - '0';
    c = getchar();
  }
  return ret;
}

char str1[4010];
char str2[4010];

int main(){
  while(~scanf("%s %s",str1,str2)){
    int ans = 0;
    for(int i=0; str1[i]; i++){
      for(int j=0; str2[j]; j++){
        if(str1[i] == str2[j]){
          int tmp = 0;
          int ii = i;
          int jj = j;
          while(str1[ii] && str1[ii++] == str2[jj++])
            ++tmp;
          ans = max(ans, tmp);
        }
      }
    }
    print(ans);
  }
  return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;

struct Suffix_Array {
    string str;
    int strlen, nowlen;
    vector<int> rank, tmp, sa, lcp;
    Suffix_Array(string news = "", bool reqlcp = 0) {
        str = news;
        strlen = str.size();
        nowlen = 0;
        rank.resize(strlen + 1);
        tmp.resize(strlen + 1);
        sa.resize(strlen + 1);
        constuct_sa();
        if(reqlcp) constuct_lcp();
    }

    void constuct_sa() {
        auto cmp = [&](int l, int r) {
            if(rank[l] != rank[r]) return rank[l] < rank[r];
            int rx = l + nowlen <= strlen ? rank[l + nowlen] : -1;
            int ly = r + nowlen <= strlen ? rank[r + nowlen] : -1;
            return rx < ly;
        };

        for(int i = 0; i <= strlen; ++i) {
            sa[i] = i;
            rank[i] = i < strlen ? str[i] : -1;
        }
        for(nowlen = 1; nowlen <= strlen; nowlen *= 2) {
            sort(sa.begin(), sa.end(), cmp);
            tmp[sa[0]] = 0;
            for(int i = 1; i <= strlen; ++i)
                tmp[sa[i]] = tmp[sa[i - 1]] +
                             (cmp(sa[i - 1], sa[i]) ? 1 : 0);
            for(int i = 0; i <= strlen; ++i) rank[i] = tmp[i];
        }
    }
    // Longest Common Prefix Array
    void constuct_lcp() {
        lcp.resize(strlen + 1);
        for(int i = 0; i <= strlen; ++i) rank[sa[i]] = i;
        int h = 0;
        lcp[0] = 0;
        for(int i = 0; i < strlen; ++i) {
            int j = sa[rank[i] - 1];
            if(h > 0) --h;
            for(; j + h < strlen && i + h < strlen; ++h)
                if(str[j + h] != str[i + h]) break;
            lcp[rank[i] - 1] = h;
        }
    }

    bool contain(string &nowt) {
        int lef = 0, righ = strlen, tsize = nowt.size();
        while(righ - lef > 1) {
            int mid = (lef + righ) / 2;
            if(str.compare(sa[mid], tsize, nowt) < 0)
                lef = mid;
            else
                righ = mid;
        }
        return str.compare(sa[righ], tsize, nowt) == 0;
    }
};

string s,t;

int solve();

int main(){
    while(cin >> s){
        cin >> t;
        cout << solve() << endl;
    }
    return 0;
}

int solve(){
    int ans = 0;
    string st = s + "#" + t;
    Suffix_Array suf(st,1);
    for(int i = 0;i < st.size();++i)
        if((suf.sa[i] < s.size()) != (suf.sa[i+1] < s.size()))
            ans = max(ans,suf.lcp[i]);
    return ans;
}

C++: #include <iostream>
#include <string>
#include <algorithm>
using namespace std;

#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define rep(i,n) REP(i,0,n)

int dp[2][4010];

int main(){
	string in1,in2;
	while(cin>>in1>>in2){
		int n = in1.size();
		int m = in2.size();
		int ret = 0;
		rep(i,2)rep(j,m+1)dp[i][j]=0;
		REP(i,1,n+1){
			int cur = i%2;
			int next = (i+1)%2;
			REP(j,1,m+1){
				if( in1[i-1]==in2[j-1] ){
					dp[next][j] = dp[cur][j-1] + 1;
					ret = max(ret,dp[next][j]);
				}
			}
		}
		printf("%d\n",ret);
	}
	return 0;
}

C++: #include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<string>

using namespace std;

#define rep(i,n) for(int i=0;i<int(n);i++)
#define reps(i,n) for(int i=1;i<=int(n);i++)
#define sint(i) scanf("%d",&i);
#define sintt(i,j) scanf("%d%d",&i,&j);
#define sinttt(i,j,k) scanf("%d%d%d",&i,&j,&k);
#define sintttt(i,j,k,m) scanf("%d%d%d%d",&i,&j,&k,&m);

#define INF 1010000000
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};

short dp[4001][4001];

int main(){
	while(1){
		string a,b;
		cin>>a>>b;
		
		if(b.size()==0){
			break;
		}
		
		rep(i,4001)rep(j,4001)dp[i][j]=0;
		
		short maxi=0;
		reps(i,a.size()){
			reps(j,b.size()){
				if(a[i-1]==b[j-1]){
					dp[i][j]=dp[i-1][j-1]+1;
				}
				maxi=max(maxi,dp[i][j]);
			}
		}
		
		printf("%d\n",maxi);
	}
}

C++: #include<bits/stdc++.h>
#define lld long long int
#define str string


using namespace std;

lld f();
lld ster,leg,leg2,ans=0,ans2=0;

str moji,moji2,cut;

int main(){

    cin >> moji >> moji2;
    leg=moji.size();
    leg2=moji2.size();

    cout << f() << endl;

return 0;
}

lld f(){
    for(int a=0;a<leg;a++){
            for(int b=1;b<leg-a;b++){
        cut = moji.substr(a,b);
        ans=(moji2.find(cut)!=-1?b:ans);
        }

    ans2=(ans>ans2?ans:ans2);
    }
    return ans2;
}

C++: #include <iostream>
#include <string>
#include <algorithm>

std::string s1,s2;

int dp[4001][4001];

int main() {
    
    while(1) {
        
        if(std::cin.eof())
            break;
        
        std::cin>>s1>>s2;
        
        for(int i=1;i<=s1.size();++i){
            for(int j=1;j<=s2.size();++j){
                if(s1[i]==s2[j])
                    dp[i][j]=dp[i-1][j-1]+1;
            }
        }
        
        int ans=0;
        
        for(int i=1;i<=s1.size();++i){
            for(int j=1;j<=s2.size();++j){
                ans=std::max(ans,dp[i][j]);
            }
        }
        
        std::cout<<ans<<std::endl;
    }
    
    return 0;
}

C++: #include <iostream>
#include <cstdio>
using namespace std;
#define FOR(i,a,b) for (int i=(a);i<(b);i++)
#define REP(i,n) for (int i=0;i<(n);i++)
#define PB push_back
#define MP make_pair
#define LL long long 
const int INF = 1145141919;

int dp[4002][4002];

int main(){
	string s1, s2;
	while (cin >> s1){
		cin >> s2;
		int ans = 0;
		memset (dp, 0, sizeof(dp));
		REP (i, s1.size()){
			REP (j, s2.size()){
				if (s1[i] == s2[j]){
					dp[i+1][j+1] = dp[i][j] + 1;
					ans = max (ans, dp[i+1][j+1]);
				}
			}
		}
		cout << ans << endl;
	}	
}