#include "bits/stdc++.h"
using namespace std;
#ifdef _DEBUG
#include "dump.hpp"
#else
#define dump(...)
#endif

//#define int long long
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)
const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)(1e9) + 7;
template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

struct MinimumCostFlow {
	using Flow = int;
	using Cost = int;
	const Cost kInfCost = INF;
	struct Edge {
		int to, rev;
		Flow cap;
		Cost cost;
		Edge() {}
		Edge(int to, int rev, Flow cap, Cost cost) :to(to), rev(rev), cap(cap), cost(cost) {}
	};
	int n;
	vector<vector<Edge>> g;
	vector<Cost> dist;
	vector<int> prevv, preve;
	MinimumCostFlow(int n) :n(n), g(n), dist(n), prevv(n), preve(n) {}
	void addArc(int from, int to, Flow cap, Cost cost) {
		g[from].emplace_back(to, (int)g[to].size(), cap, cost);
		g[to].emplace_back(from, (int)g[from].size() - 1, 0, -cost);
	}
	// s??????t????????????f???????°??????¨???
	// ??????????????´?????? -1
	Cost minimumCostFlow(int s, int t, Flow f) {
		Cost total = 0;
		while (f > 0) {
			// Bellman-Ford
			fill(dist.begin(), dist.end(), kInfCost);
			dist[s] = 0;
			bool update = true;
			while (update) {
				update = false;
				for (int v = 0; v < n; v++) {
					if (dist[v] == kInfCost)continue;
					for (int i = 0; i < g[v].size(); i++) {
						Edge &e = g[v][i];
						if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
							dist[e.to] = dist[v] + e.cost;
							prevv[e.to] = v;
							preve[e.to] = i;
							update = true;
						}
					}
				}
			}
			// ????????\???????????????
			if (dist[t] == kInfCost)
				return -1;
			// ?????????????????£??????????????????
			Flow d = f;
			for (int v = t; v != s; v = prevv[v])
				d = min(d, g[prevv[v]][preve[v]].cap);
			f -= d;
			total += dist[t] * d;
			for (int v = t; v != s; v = prevv[v]) {
				Edge &e = g[prevv[v]][preve[v]];
				e.cap -= d;
				g[v][e.rev].cap += d;
			}
		}
		return total;
	}
};

int levenshteinDistance(const string &a, const string &b) {
	int m = a.size(), n = b.size();
	vector<vector<int>> ld(m + 1, vector<int>(n + 1, INF));

	rep(i, 0, m + 1)ld[i][0] = i;
	rep(j, 0, n + 1)ld[0][j] = j;
	rep(i, 1, m + 1)rep(j, 1, n + 1) {
		ld[i][j] = min({
			// ?????\(a???)
			ld[i - 1][j] + 1,
			// ??????(b??????) or ?????\(b???)
			ld[i][j - 1] + 1,
			// ?????? 
			ld[i - 1][j - 1] + (a[i - 1] != b[j - 1])
		});
	}
	return ld[m][n];
}

vector<string> split(const string &input, const char &delimiter) {
	vector<string> ret;
	string w;
	for (const char &c : input) {
		if (c == delimiter) {
			ret.emplace_back(w);
			w.clear();
		}
		else w += c;
	}
	if (input.back() == delimiter)ret.emplace_back("");
	else ret.emplace_back(w);
	return ret;
}

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	for (int N, M; cin >> N >> M;) {
		unordered_map<string, int> cnt; cin.ignore();
		vector<string> s;
		rep(i, 0, N) {
			string text; getline(cin, text);
			vector<string> tmp = split(text, ' ');
			rep(j, 0, tmp.size()) {
				cnt[tmp[j]]++;
			}
			s.insert(s.end(), tmp.begin(), tmp.end());
		}
		sort(all(s));
		s.erase(unique(s.begin(), s.end()), s.end());
		N = s.size();
		vector<string> t(M); rep(i, 0, M) {
			cin >> t[i];
		}
		MinimumCostFlow mcf(N + M + 2);
		int src = mcf.n - 2, snk = src + 1;
		rep(i, 0, N)rep(j, 0, M) {
			mcf.addArc(i, N + j, 1, levenshteinDistance(s[i], t[j])*cnt[s[i]]);
		}
		rep(i, 0, N) {
			mcf.addArc(src, i, 1, 0);
		}
		rep(i, 0, M) {
			mcf.addArc(N + i, snk, 1, 0);
		}
		cout << mcf.minimumCostFlow(src, snk, N) << endl;
	}
	return 0;
}

Measured memory_bytes: 10652