#include <bits/stdc++.h>

int ri() {
	int n;
	scanf("%d", &n);
	return n;
}

/* copied from https://gist.github.com/MiSawa/9759784 */
/* edited by QCFium */
struct Dinic {
private:
	typedef int64_t Cap;
	static const Cap INF = 1000000000000000000;
	
	struct LCNode {
		typedef LCNode *Ptr;
		Ptr ch[2], par, min_node;
		Cap val, min_val, lazy;
		int name;
		LCNode() : par(0), min_node(this), val(INF), min_val(INF), lazy(0) {
			ch[0] = ch[1] = 0;
		}
		inline void push() {
			if (lazy == 0) return;
			val += lazy; min_val += lazy;
			for (int i = 0; i < 2; i++) if (ch[i]) ch[i]->lazy += lazy;
			lazy = 0;
		}
		inline void update() {
			push();
			if (ch[0]) {
				min_val = ch[0]->min_val + ch[0]->lazy;
				min_node = ch[0]->min_node;
			}
			if (!ch[0] || min_val > val) {
				min_val = val; min_node = this;
			}
			if (ch[1] && min_val > ch[1]->min_val + ch[1]->lazy) {
				min_val = ch[1]->min_val + ch[1]->lazy;
				min_node = ch[1]->min_node;
			}
		}
		inline void set_value(Cap v) { expose(); val = v; update(); }
		inline Cap get_value() { expose(); return val; }
		inline Ptr get_min_node_on_path() { expose(); return min_node; }
		inline void add_to_path(Cap c) { expose(); lazy += c; push(); }
		inline int state() {
			if(par && par->ch[0] == this) return -1;
			if(par && par->ch[1] == this) return +1;
			return 0;
		}
		inline void rotate() {
			Ptr p = par; p->push(); push();
			bool lr = state()+1;
			if (p->state()) p->par->ch[p->state()>0] = this;
			par = p->par;
			p->ch[lr] = ch[!lr];
			if (ch[!lr]) ch[!lr]->par = p;
			(p->par = this)->ch[!lr] = p;
			p->update(); update();
		}
		inline void splay() {
			while (state()) {
				int s = state() * par->state();
				if (s) (s == 1 ? par : this)->rotate();
				rotate();
			}
			push();
		}
		inline void expose() {
			if (!par) return;
			for (Ptr p = this; p; p = p->par) p->splay();
			for (Ptr p = this; p->par; p = p->par) p->par->ch[1] = p;
			splay();
		}
		inline void cut() {
			expose();
			if (!ch[0]) return;
			ch[0]->par = 0;
			ch[0]->push();
			ch[0] = 0;
			update();
		}
		inline void link_to(Ptr p) {
			expose();
			par = p;
		}
		inline Ptr find_root() {
			expose();
			Ptr p = this;
			while (p->ch[0]) p = p->ch[0];
			p->expose();
			return p;
		}
	};
	struct E{
		int dst;
		Cap cap;
		int rev;
		E(int dst, Cap cap, int rev) : dst(dst), cap(cap), rev(rev) {}
	};
	int n;
	std::vector<std::vector<E> > g;
	std::vector<int> level, active;
	std::vector<LCNode> lc;
	inline void unuse_edge(E &e) {
		E &ee = g[e.dst][e.rev]; int u = ee.dst;
		Cap use = ee.cap - lc[u].get_value();
		e.cap += use; ee.cap -= use;
		active[u] = false;
		lc[u].cut(); lc[u].set_value(INF);
	}
	inline void init(){
		lc.resize(n);
		active.assign(n, false);
		for (int i = 0; i < n; i++) lc[i].name = i;
	}
	Cap dfs(const int &s, const int &t) {
		std::vector<int> iter(n);
		for (int i = 0; i < n; i++) iter[i] = (int) (g[i].size()) - 1;
		Cap res = 0;

		while(1) {
			const int &u = lc[t].find_root()->name;
			if (u == s) {
				Cap f = lc[t].get_min_node_on_path()->get_value();
				res += f;
				lc[t].add_to_path(-f);
				while (1) {
					int v = lc[t].get_min_node_on_path()->name;
					Cap f = lc[v].get_value();
					if (f > 0) break;
					unuse_edge(g[v][iter[v]]);
				}
			} else {
				for (int &i = iter[u]; i >= 0; i--) {
					E &e = g[u][i], &ee = g[e.dst][e.rev]; int v = e.dst;
					if (level[u] - 1 != level[v] || ee.cap <= 0) continue;
					active[u] = true;
					lc[u].set_value(ee.cap);
					lc[u].link_to(&lc[v]);
					break;
				}
				if (active[u]) continue;
				if (u == t) break;
				level[u] = -1;
				for (auto& e : g[u]) if (active[e.dst] && iter[e.dst] == e.rev)
					unuse_edge(g[e.dst][e.rev]);
			}
		}
		for (int i = 0; i < n; i++) if (active[i]) unuse_edge(g[i][iter[i]]);
		return res;
	}

public:
	Dinic(int n) : n(n), g(n) {}
	inline void add_hen(int src, int dst, Cap cap, bool direct) {
		if (src == dst) return;
		g[src].push_back(E(dst, cap, g[dst].size()));
		g[dst].push_back(E(src, direct ? 0 : cap , g[src].size() - 1));
	}
	Cap run(int s, int t) { // O(NMlogN)
		init();
		std::vector<int> q(n);
		for (Cap flow = 0; ; ) {
			level.assign(n, -1);
			int ql = 0, qr = 0;
			level[q[qr++] = s] = 0;
			while (ql != qr && level[t] == -1) {
				int u = q[ql++];
				for (auto& e : g[u]) if (e.cap > 0 && level[e.dst] == -1)
					level[q[qr++] = e.dst] = level[u] + 1;
			}
			if (level[t] == -1) return flow;
			flow += dfs(s, t);
		}
	}
};


int main() {
	int n = ri();
	std::string s[n];
	for (auto &i : s) std::cin >> i;
	std::sort(s, s + n);
	
	std::map<std::string, int> odd, even;
	int odds = 0, evens = 0;
	for (int i = 0; i < n; i++) {
		if (s[i].size() & 1) odd[s[i]] = odds++;
		else even[s[i]] = evens++;
	}
	
	Dinic dinic(n + 2);
	int cnt = 0;
	for (auto &i : odd) {
		for (int j = 0; j < (int) i.first.size(); j++) {
			std::string cur = i.first;
			cur.erase(cur.begin() + j);
			if (even.count(cur)) dinic.add_hen(cnt + 1, even[cur] + odds + 1, 1, true);
		}
		cnt++;
	}
	cnt = 0;
	for (auto &i : even) {
		for (int j = 0; j < (int) i.first.size(); j++) {
			std::string cur = i.first;
			cur.erase(cur.begin() + j);
			if (odd.count(cur)) dinic.add_hen(odd[cur] + 1, cnt + odds + 1, 1, true);
		}
		cnt++;
	}
	for (int i = 1; i <= odds; i++) dinic.add_hen(0, i, 1, true);
	for (int i = odds + 1; i <= n; i++) dinic.add_hen(i, n + 1, 1, true);
	std::cout << dinic.run(0, n + 1) << std::endl;
	
	return 0;
}



Measured memory_bytes: 93304