// Arup Guha
// 4/12/2023
// Solution to 2017 MAPS Problem E: King of Spades
// This solution is a bit faster than my "original" - it uses an int for the hash function
// and calculates a rolling hash.

import java.util.*;
import java.io.*;

public class kingofspades2 {

	final public static int MOD = 10000007;
	final public static int BASE = 101;
	
	final public static int[] VALS = {1,2,3,4,5,6,7,8,9,10,10,10,10,0,0,0,0};
	
	public static TreeSet<Integer> kList1;
	public static TreeSet<Integer> kList2;
	public static int n;
	public static String[] list1;
	public static int[] list1Suits;
	public static int[] list1Kinds;
	
	public static int m;
	public static String[] list2;
	public static int[] list2Suits;
	public static int[] list2Kinds;
	
	public static void main(String[] args) throws Exception {
	
		// Basic stuff.
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		n = Integer.parseInt(tok.nextToken());
		list1 = new String[n];
		list1Suits = new int[n];
		list1Kinds = new int[n];
		
		m = Integer.parseInt(tok.nextToken());
		list2 = new String[m];
		list2Suits = new int[m];
		list2Kinds = new int[m];
		kList1 = new TreeSet<Integer>();
		kList2 = new TreeSet<Integer>();
		
		// Read lists.
		tok = new StringTokenizer(stdin.readLine());
		for (int i=0; i<n; i++) list1[i] = tok.nextToken();
		tok = new StringTokenizer(stdin.readLine());
		for (int i=0; i<m; i++) list2[i] = tok.nextToken();
		
		// Store where there are K of S.
		for (int i=0; i<n; i++) if (list1[i].equals("KS")) kList1.add(i);
		for (int i=0; i<m; i++) if (list2[i].equals("KS")) kList2.add(i);
		
		// Explicitly store kinds and suits with my integer codes.
		for (int i=0; i<n; i++) {
			list1Kinds[i] = convert(list1[i].charAt(0));
			list1Suits[i] = convert(list1[i].charAt(1));
		}
		for (int i=0; i<m; i++) {
			list2Kinds[i] = convert(list2[i].charAt(0));
			list2Suits[i] = convert(list2[i].charAt(1));
		}
		
		// Get cumulative frequencies.
		int[][] cf1 = getCF(list1);
		int[][] cf2 = getCF(list2);
		
		int res = 0;
		
		// For rolling hash.
		int[] mult = new int[17];
		mult[16] = 1;
		for (int i=15; i>=0; i--) mult[i] = (mult[i+1]*BASE)%MOD;
		
		// Try each length.
		for (int len=1; len<=100; len++) {
			
			// Can't get a sequence of this length...
			if (len > n || len > m) break;
			
			// will map hash in first list to starting position.
			HashMap<Integer, LinkedList<Integer>> map = new HashMap<Integer, LinkedList<Integer>>();
			
			// Initial hash.
			int myh = getHash(cf1, 0, len-1);
			
			// sequence is from index s to index s+len-1.
			for (int s=0; s+len<=n; s++) {
				
				// Roll hash.
				if (s > 0) {
					myh = (myh-mult[list1Kinds[s-1]]+mult[list1Kinds[s+len-1]]+MOD)%MOD;
					myh = (myh-mult[list1Suits[s-1]]+mult[list1Suits[s+len-1]]+MOD)%MOD;
				}
				

				// Skip streaks with K of S.
				Integer nextKS = kList1.higher(s-1);
				if (nextKS != null && nextKS <= s+len-1) continue;
				
				// Add entry, if necessary.
				if (!map.containsKey(myh)) {
					LinkedList<Integer> tmp = new LinkedList<Integer>();
					map.put(myh, tmp);
				}
				
				// Now add this item to myh's list.
				map.get(myh).add(s);
			}
			
			// Initial hash for second substring.
			myh = getHash(cf2, 0, len-1);
			
			// t is starting position in second string.
			for (int t=0; t+len<=m; t++) {
				
				// roll hash.
				if (t > 0) {
					myh = (myh-mult[list2Kinds[t-1]]+mult[list2Kinds[t+len-1]]+MOD)%MOD;
					myh = (myh-mult[list2Suits[t-1]]+mult[list2Suits[t+len-1]]+MOD)%MOD;					
				}
				
				
				// Skip if this substring has K of S.
				Integer nextKS = kList2.higher(t-1);
				if (nextKS != null && nextKS <= t+len-1) continue;
				
				// We got a hit, verify it!
				if (map.containsKey(myh)) {
					LinkedList<Integer> tmp = map.get(myh);
					
					// Break here is key.
					for (Integer x: tmp) {
						int score = verify(x, cf1, t, cf2, len);
						res = Math.max(res, score);
						if (score != 0) break;
					}
				}
			}
		} // end len loop.
		
		// Ta da!
		System.out.println(res);
	}
	
	// Just verifies the results of the hash by looking at the CF arrays.
	public static int verify(int s1, int[][] cf1, int s2, int[][] cf2, int len) {
		
		int score = 0;
		for (int i=0; i<cf1.length; i++) {
			int cnt1 = cf1[i][s1+len]-cf1[i][s1];
			int cnt2 = cf2[i][s2+len]-cf2[i][s2];
			
			// Either suit or kind count doesn't match.
			if (cnt1 != cnt2) return 0;
			
			// Update score.
			score += cnt1*VALS[i];
		}
		
		// We get the score for both sets.
		return 2*score;
	}
	
	// Returns all CF arrays (17) associated with list.
	public static int[][] getCF(String[] list) {
	
		int len = list.length;
		int[][] cf = new int[17][len+1];
		for (int i=0; i<len; i++) {
			
			// Set to previous value.
			for (int j=0; j<17; j++) cf[j][i+1] = cf[j][i];
			
			int idx1 = convert(list[i].charAt(0));
			int idx2 = convert(list[i].charAt(1));
			
			// Add 1 at these two spots.
			cf[idx1][i+1]++;
			cf[idx2][i+1]++;
		}
	
		return cf;
	}
	
	// My hash function for the range of cards in cf from sI to eI, inclusive.
	public static int getHash(int[][] cf, int sI, int eI) {
		int res = 0;
		for (int i=0; i<17; i++)
			res = (BASE*res + cf[i][eI+1]-cf[i][sI])%MOD;
		return res;
	}
	
	// My code for which index to store each kind and suit.
	public static int convert(char c) {
		if (c == 'A') return 0;
		if (c >= '2' && c <= '9') return c - '1';
		if (c == 'T') return 9;
		if (c == 'J') return 10;
		if (c == 'Q') return 11;
		if (c == 'K') return 12;
		if (c == 'S') return 13;
		if (c == 'H') return 14;
		if (c == 'D') return 15;
		return 16;
	}
}