import java.io.*; import java.util.*; public class Solution { int size() { try { return sc.nextInt(); } catch (Exception e) { return -1; } } public Solution () { for (;;) { int N = size(); if (N == -1) return; char [][] B = sc.nextChars(N); @SuppressWarnings("unchecked") List<Integer> [] G = new List[N]; for (int i : rep(N)) G[i] = new ArrayList<>(); for (int i : rep(N)) for (int j : rep(i)) if (test(B[i], B[j])) { G[i].add(j); G[j].add(i); } int match = maxMatching(G); int res = N - match; print(res); } } boolean test(char [] X, char [] Y) { return test2(X, Y) || test2(Y, X); } boolean test2(char [] X, char [] Y) { int S = X.length + Y.length, p = 0, q = S-1; while (q >= 0) { if (ch(X, Y, p) != ch(X, Y, q)) return false; ++p; --q; } return true; } char ch(char [] X, char [] Y, int p) { if (p < X.length) return X[p]; else return Y[p - X.length]; } static int lca(int[] match, int[] base, int[] p, int a, int b) { boolean[] used = new boolean[match.length]; while (true) { a = base[a]; used[a] = true; if (match[a] == -1) break; a = p[match[a]]; } while (true) { b = base[b]; if (used[b]) return b; b = p[match[b]]; } } static void markPath(int[] match, int[] base, boolean[] blossom, int[] p, int v, int b, int children) { for (; base[v] != b; v = p[match[v]]) { blossom[base[v]] = blossom[base[match[v]]] = true; p[v] = children; children = match[v]; } } static int findPath(List<Integer>[] graph, int[] match, int[] p, int root) { int n = graph.length; boolean[] used = new boolean[n]; Arrays.fill(p, -1); int[] base = new int[n]; for (int i = 0; i < n; ++i) base[i] = i; used[root] = true; int qh = 0; int qt = 0; int[] q = new int[n]; q[qt++] = root; while (qh < qt) { int v = q[qh++]; for (int to : graph[v]) { if (base[v] == base[to] || match[v] == to) continue; if (to == root || match[to] != -1 && p[match[to]] != -1) { int curbase = lca(match, base, p, v, to); boolean[] blossom = new boolean[n]; markPath(match, base, blossom, p, v, curbase, to); markPath(match, base, blossom, p, to, curbase, v); for (int i = 0; i < n; ++i) if (blossom[base[i]]) { base[i] = curbase; if (!used[i]) { used[i] = true; q[qt++] = i; } } } else if (p[to] == -1) { p[to] = v; if (match[to] == -1) return to; to = match[to]; used[to] = true; q[qt++] = to; } } } return -1; } public static int maxMatching(List<Integer>[] graph) { int n = graph.length; int[] match = new int[n]; Arrays.fill(match, -1); int[] p = new int[n]; for (int i = 0; i < n; ++i) if (match[i] == -1) { int v = findPath(graph, match, p, i); while (v != -1) { int pv = p[v]; int ppv = match[pv]; match[v] = pv; match[pv] = v; v = ppv; } } int matches = 0; for (int i = 0; i < n; ++i) if (match[i] != -1) ++matches; return matches / 2; } private static final boolean ONE_TEST_CASE = true; private static int [] rep(int N) { return rep(0, N); } private static int [] rep(int S, int T) { if (T <= S) return new int [0]; int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; } //////////////////////////////////////////////////////////////////////////////////// private final static IOUtils.MyScanner sc = new IOUtils.MyScanner(); private static void print (Object o, Object ... A) { IOUtils.print(o, A); } private static class IOUtils { public static class MyScanner { public String next() { newLine(); return line[index++]; } public int nextInt() { return Integer.parseInt(next()); } public char [] nextChars() { return next ().toCharArray (); } public char [][] nextChars(int N) { char [][] res = new char [N][]; for (int i = 0; i < N; ++i) res[i] = nextChars(); return res; } ////////////////////////////////////////////// private boolean eol() { return index == line.length; } private String readLine() { try { return r.readLine(); } catch (Exception e) { throw new Error (e); } } private final java.io.BufferedReader r; private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); } private MyScanner (java.io.BufferedReader r) { try { this.r = r; while (!r.ready()) Thread.sleep(1); start(); } catch (Exception e) { throw new Error(e); } } private String [] line; private int index; private void newLine() { if (line == null || eol()) { line = split(readLine()); index = 0; } } private String [] split(String s) { return s.length() > 0 ? s.split(" ") : new String [0]; } } private static String build(Object o, Object ... A) { return buildDelim(" ", o, A); } private static String buildDelim(String delim, Object o, Object ... A) { StringBuilder b = new StringBuilder(); append(b, o, delim); for (Object p : A) append(b, p, delim); return b.substring(delim.length()); } ////////////////////////////////////////////////////////////////////////////////// private static void start() { if (t == 0) t = millis(); } private static void append(StringBuilder b, Object o, String delim) { if (o.getClass().isArray()) { int len = java.lang.reflect.Array.getLength(o); for (int i = 0; i < len; ++i) append(b, java.lang.reflect.Array.get(o, i), delim); } else if (o instanceof Iterable<?>) for (Object p : (Iterable<?>) o) append(b, p, delim); else { if (o instanceof Double) o = new java.text.DecimalFormat("#.############").format(o); b.append(delim).append(o); } } private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out); private static void print(Object o, Object ... A) { pw.println(build(o, A)); } private static void err(Object o, Object ... A) { System.err.println(build(o, A)); } private static void exit() { IOUtils.pw.close(); System.out.flush(); err("------------------"); err(IOUtils.time()); System.exit(0); } private static long t; private static long millis() { return System.currentTimeMillis(); } private static String time() { return "Time: " + (millis() - t) / 1000.0; } private static void run(int N) { for (int n = 1; n <= N; ++n) new Solution(); exit(); } } public static void main(String[] args) throws IOException { int N = ONE_TEST_CASE ? 1 : sc.nextInt(); IOUtils.run(N); } }