import java.util.Arrays; import java.util.Scanner; //import java.util.concurrent.ThreadLocalRandom; public class LCS2 { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int[] a = new int[n]; for (int i = 0; i < n; i++) { a[i] = scanner.nextInt(); } int m = scanner.nextInt(); int[] b = new int[m]; for (int i = 0; i < m; i++) { b[i] = scanner.nextInt(); } System.out.println(third_lcs2(a, b)); // System.out.println(alt_lcs2(a, b, n, m)); // while (true) { //// int n = ThreadLocalRandom.current().nextInt(1, 101); //// int m = ThreadLocalRandom.current().nextInt(1, 101); // int n = ThreadLocalRandom.current().nextInt(1, 20); // int m = ThreadLocalRandom.current().nextInt(1, 20); // int[] a = new int[n]; // int[] b = new int[m]; // for (int i = 0; i < a.length; i++) { // a[i] = ThreadLocalRandom.current().nextInt(-999999999, 1000000000); // } // for (int i = 0; i < b.length; i++) { // b[i] = ThreadLocalRandom.current().nextInt(-999999999, 1000000000); // } // int r1 = lcs2(a, b); // int r2 = alt_lcs2(a, b, n, m); // if (r1 == r2) // System.out.println("ok"); // else { // System.out.println(Arrays.toString(a)); // System.out.println(Arrays.toString(b)); // System.out.println("Wrong answer " + r1 + " " + r2); // break; // } // } } public static int[][] editDistance(int[] A, int[] B) { int m = B.length; int n = A.length; int[][] D = new int[n + 1][m + 1]; for (int i = 0; i < n + 1; i++) { D[i][0] = i; } for (int j = 0; j < m + 1; j++) { D[0][j] = j; } for (int j = 1; j < m + 1; j++) { for (int i = 1; i < n + 1; i++) { int insertion = D[i][j - 1] + 1; int deletion = D[i - 1][j] + 1; int match = D[i - 1][j - 1]; int mismatch = D[i - 1][j - 1] + 1; if (A[i - 1] == B[j - 1]) { D[i][j] = Math.min(insertion, Math.min(deletion, match)); } else { D[i][j] = Math.min(insertion, Math.min(deletion, mismatch)); } } } return D; } public static int lcs2(int[] a, int[] b) { int D[][] = editDistance(a, b); return lcs2(a.length, b.length, D); } private static int lcs2(int i, int j, int[][] D) { if (i == 0 && j == 0) return 0; if (i > 0 && D[i][j] == D[i - 1][j] + 1) return lcs2(i - 1, j, D); if (j > 0 && D[i][j] == D[i][j - 1] + 1) return lcs2(i, j - 1, D); else if (D[i][j] == D[i - 1][j - 1]) return 1 + lcs2(i - 1, j - 1, D); else return lcs2(i - 1, j - 1, D); } public static int alt_lcs2(int[] a, int[] b, int i, int j) { if (i == 0 || j == 0) return 0; if (a[i - 1] == b[j - 1]) return 1 + alt_lcs2(a, b, i - 1, j - 1); else return Math.max(alt_lcs2(a, b, i, j - 1), alt_lcs2(a, b, i - 1, j)); } public static int third_lcs2(int[] a, int[] b) { int m = b.length; int n = a.length; int[][] D = new int[n + 1][m + 1]; for (int j = 1; j < m + 1; j++) { for (int i = 1; i < n + 1; i++) { if (a[i - 1] == b[j - 1]) { D[i][j] = D[i - 1][j - 1] + 1; } else { D[i][j] = Math.max(D[i - 1][j], D[i][j - 1]); } } } return D[n][m]; } }