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

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()

		dp := make([][]int, len(S)+1)
		for i := range dp {
			dp[i] = make([]int, len(T)+1)
		}

		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 <string>
using namespace std;

#define MAX 4001

int dp[MAX][MAX];

int main(void) {
  string s, t;
  while (cin >> s >> t) {
    for (int i = 0; i < s.size(); i++) {
      for (int j = 0; j < t.size(); j++) {
	if (s[i] == t[j]) {
	  dp[i][j] = 1;
	} else {
	  dp[i][j] = 0;
	}
      }
    }

    for (int i = 1; i < s.size(); i++) {
      for (int j = 1; j < t.size(); j++) {
	if (dp[i][j] == 0) continue;
	dp[i][j] += dp[i - 1][j - 1];
      }
    }

    int ans = 0;
    for (int i = 0; i < s.size(); i++) {
      for (int j = 0; j < t.size(); j++) {
	ans = max(ans, dp[i][j]);
      }
    }
    cout << ans << endl;
  }
  return 0;
}

C++: #include<iostream>
#include<cstring>

using namespace std;

const int MAX = 4001;

int dp[MAX][MAX];
string in[2];

void solve(){

  for(int i = 0; i < in[0].length(); i++){
    for(int j = 0; j < in[1].length(); j++){
      if(in[0][i] == in[1][j]) dp[i+1][j+1] = dp[i][j]+1;
    }
  }
  int out = 0;
  for(int i = 1; i <= in[0].length(); i++)
    for(int j = 1; j <= in[1].length(); j++)
      out = max(out,dp[i][j]);
  cout << out << endl;
}

int main(){
  while(cin >> in[0] >> in[1]){
    memset(dp,0,sizeof(dp));
    solve();
  }
  return 0;
}

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

// ----- SuffixArray -----

class SuffixArray
{
  int N, K;
  string S;
  vector<int> sa, lcp;

public:
  SuffixArray(string S) : N{static_cast<int>(S.size())}, K{1}, S{S}, sa(N + 1), lcp(N)
  {
    // initialize for 1 char
    for (auto i = 0; i <= N; i++)
    {
      sa[i] = i;
    }
    vector<int> rank(N + 1);
    for (auto i = 0; i < N; i++)
    {
      rank[i] = static_cast<int>(S[i]);
    }
    rank[N] = -1;
    // lambda for comparing
    auto compare_sa = [&](auto i, auto j) {
      if (rank[i] != rank[j])
      {
        return rank[i] < rank[j];
      }
      else
      {
        int ri{i + K <= N ? rank[i + K] : -1};
        int rj{j + K <= N ? rank[j + K] : -1};
        return ri < rj;
      }
    };
    // construct sa with rank
    vector<int> tmp(N + 1);
    for (; K <= N; K *= 2)
    {
      sort(sa.begin(), sa.end(), compare_sa);
      tmp[sa[0]] = 0;
      for (auto i = 1; i <= N; i++)
      {
        tmp[sa[i]] = tmp[sa[i - 1]] + (compare_sa(sa[i - 1], sa[i]) ? 1 : 0);
      }
      swap(rank, tmp);
    }
    // construct lcp with sa and rank
    for (auto i = 0; i <= N; i++)
    {
      rank[sa[i]] = i;
    }
    int h{0};
    lcp[0] = 0;
    for (auto i = 0; i < N; i++)
    {
      int j{sa[rank[i] - 1]};
      if (h > 0)
      {
        --h;
      }
      for (; j + h < N && i + h < N; ++h)
      {
        if (S[j + h] != S[i + h])
        {
          break;
        }
      }
      lcp[rank[i] - 1] = h;
    }
  }

  int operator[](int i) const
  {
    return sa[i];
  }

  vector<int> const &LCP()
  {
    return lcp;
  }

  bool contain(string const &T) const
  {
    int b{lower_bound(T)};
    return b <= N && S.compare(sa[b], T.size(), T) == 0;
  }

  int count(string const &T) const
  {
    int lb{lower_bound(T)};
    int ub{upper_bound(T)};
    if (lb > ub)
    {
      return 0;
    }
    return ub - lb + 1;
  }

private:
  template <typename T>
  void binary_search(int &a, int &b, T cmp) const
  {
    while (abs(a - b) > 1)
    {
      int c{(a + b) / 2};
      if (cmp(c))
      {
        a = c;
      }
      else
      {
        b = c;
      }
    }
  }

  int lower_bound(string const &T) const
  {
    int a{-1}, b{N + 1};
    auto cmp = [&](auto c) {
      return S.compare(sa[c], T.size(), T) < 0;
    };
    binary_search(a, b, cmp);
    return b;
  }

  int upper_bound(string const &T) const
  {
    int a{-1}, b{N + 1};
    auto cmp = [&](auto c) {
      return S.compare(sa[c], T.size(), T) <= 0;
    };
    binary_search(a, b, cmp);
    return a;
  }
};

// ----- main() -----

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_14_D&lang=ja

void solve_contain()
{
  string S;
  int Q;
  cin >> S >> Q;
  vector<string> T(Q);
  for (auto i = 0; i < Q; i++)
  {
    cin >> T[i];
  }
  SuffixArray sa(S);
  for (auto i = 0; i < Q; i++)
  {
    cout << (sa.contain(T[i]) ? 1 : 0) << endl;
  }
}

void solve_count()
{
  string S, T;
  cin >> S >> T;
  SuffixArray sa(S);
  cout << sa.count(T) << endl;
}

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0528

template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}

int common_sub_string(string const &S, string const &T)
{
  string U{S + "$" + T};
  int L{static_cast<int>(S.size())};
  SuffixArray sa{U};
  int ans{0};
  for (auto i = 0; i < static_cast<int>(U.size()); i++)
  {
    if ((sa[i] < L) ^ (sa[i + 1] < L))
    {
      ch_max(ans, sa.LCP()[i]);
    }
  }
  return ans;
}

int main()
{
  string S, T;
  while (cin >> S >> T)
  {
    cout << common_sub_string(S, T) << endl;
  }
}

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

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

int dp[4444][4444];
string s, t;

int main(int argc, char *argv[])
{
  while(cin >> s >> t){
    int ls = s.length();
    int lt = t.length();
    rep(i, ls) rep(j, lt) dp[i][j] = 0;
    int res = 0;
    rep(i, ls) rep(j, lt){
      if(j == 0) dp[i + 1][0] = 0;
      if(s[i] == t[j]) dp[i + 1][j + 1] = dp[i][j] + 1;
      else dp[i + 1][j + 1] = 0;
      res = max(res, dp[i + 1][j]);
    }
    cout << res << endl;
  }
  
  return 0;
}

C++: #include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
	string s, t; int roop1, roop2 = 0, save[10000], ans = 0;
	//while(cin){
	cin >> s >> t;
	//if(cin.eof())
	//break;
	for (int i = 0; i<s.size(); i++){
		for (int j = 0; j<t.size(); j++){
			if (s[i] == t[j]){
				roop1 = 0;
				save[roop2] = 0;
				while (1){
					if (s[i + roop1] == 0|| t[j + roop1] ==0){
						break;
					}
					else{
					if (s[i + roop1] == t[j + roop1]){
							save[roop2] += 1;
							roop1++;
						}
						else if (s[i + roop1] != t[j + roop1]){
							roop2++;
							break;
						}
					}
				}
			}
		}
	}
	sort(save, save + roop2 + 1);
	ans = save[roop2];
	cout << ans << endl;
	//}
	return 0;
}

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

string str1;
string str2;
int solve(){
    int count=0;
    int m=0;
    int limit1;
    int limit2;
    int limit;
    limit1 = str1.size();
    limit2 = str2.size();
    for(int i=0;i<limit2;i++){
        limit = i+limit1<limit2 ? i+limit1 : limit2;
        for(int j=i;j<limit;j++){
            if(str1[j-i] == str2[j]){
                count++;
            }else{
                m = max(m, count);
                count = 0;
            }
        }
    }
    return m;
}
int main(){
    string temp;
    while(cin >> str1 >> str2){
        if(str1.size() > str2.size()){
            temp = str1;
            str1 = str2;
            str2 = temp;
        }
        cout << solve() << endl;
    }
}