#include using namespace std; const int MAX_N = 1024; int n, m, k; struct Edge { int u, v, weight; bool operator<(Edge const& other) { return weight < other.weight; } }; vector parent, _rank; void make_set(int v) { parent[v] = v; _rank[v] = 0; } int find_set(int v) { if (v == parent[v]) return v; return parent[v] = find_set(parent[v]); } void union_sets(int a, int b) { a = find_set(a); b = find_set(b); if (a != b) { if (_rank[a] < _rank[b]) swap(a, b); parent[b] = a; if (_rank[a] == _rank[b]) _rank[a]++; } } string s[MAX_N]; long long sum = 0; vector edges; int kruskal() { int cost = 0; vector result; parent.resize(n); _rank.resize(n); for (int i = 0; i < n; i++) make_set(i); sort(edges.begin(), edges.end()); for (Edge e : edges) { if (find_set(e.u) != find_set(e.v)) { cost += e.weight; result.push_back(e); union_sets(e.u, e.v); } } return cost; } int main () { ios_base::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m >> k; for (int i = 0; i < n; i++) { cin >> s[i]; } for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { bool eq = true; for (int l = 0; l < m; l++) { if (s[i][l] != s[j][l]) { eq = false; } } if (eq) { edges.push_back({i, j, 1}); edges.push_back({j, i, 1}); } else { int diff = 0; for (int l = m; l < k; l++) { if (s[i][l] != s[j][l]) { diff++; } } edges.push_back({i, j, diff + m}); edges.push_back({j, i, diff + m}); } } } cout << kruskal() << endl; return 0; }