import java.io.*;
import java.util.*;

public class dictionary_mb_wa_greedy {
    static final int INF = 1000000000;

    static String[] removeSubstrings(String[] words) {
        int n = words.length;
        boolean[] use = new boolean[n];
        Arrays.fill(use, true);
        for (int li = 0; li < n; ++li) {
            for (int ri = 0; ri < n; ++ri) {
                use[ri] &= words[li].equals(words[ri]) && ri <= li || !words[li].contains(words[ri]);
            }
        }
        int count = 0;
        for (boolean b : use) {
            if (b) {
                ++count;
            }
        }
        String[] rv = new String[count];
        for (int i = 0, j = 0; i < n; ++i) {
            if (use[i]) {
                rv[j++] = words[i];
            }
        }
        return rv;
    }

    static class Overlap {
        final int secondOffset;
        final int overlapLength;
        final int source;
        final int target;
        public Overlap(int secondOffset, int overlapLength, int source, int target) {
            this.secondOffset = secondOffset;
            this.overlapLength = overlapLength;
            this.source = source;
            this.target = target;
        }
        public String toString() {
            return "Overlap(" + secondOffset + "," + overlapLength + ")";
        }
        static Overlap compute(String ls, String rs, int src, int trg) {
            int maxOverlap = 0;
            int maxPrefLen = 0;
            for (int prefLen = ls.length(); prefLen > 0; --prefLen) {
                for (int len = Math.min(prefLen, rs.length()); len > maxOverlap; --len) {
                    boolean ok = true;
                    for (int t = 0; t < len; ++t) {
                        ok &= ls.charAt(prefLen - len + t) == rs.charAt(t);
                    }
                    if (ok) {
                        maxOverlap = len;
                        maxPrefLen = prefLen;
                        break;
                    }
                }
            }
            return new Overlap(maxPrefLen - maxOverlap, maxOverlap, src, trg);
        }
    }

    static class AnswerNode {
        static int idSource = 0;
        static List<AnswerNode> allNodes = new ArrayList<>();

        static void cleanup() {
            idSource = 0;
            allNodes.clear();
        }

        final char ch;
        final AnswerNode parent;
        final int id = ++idSource;


        public AnswerNode() {
            this.ch = ' ';
            this.parent = null;
            allNodes.add(this);
        }

        public AnswerNode(AnswerNode parent, char ch) {
            this.ch = ch;
            this.parent = parent;
            allNodes.add(this);
        }
    }

    static void restoreAnswer(String[] words, Overlap[][] overlaps, int[] parents, int current, AnswerNode myLastNode) {
        for (int ch = 0; ch < words.length; ++ch) {
            if (parents[ch] == current) {
                Overlap ovl = current == words.length ? null : overlaps[current][ch];
                AnswerNode curr = myLastNode;
                int howMuchBack = ovl == null ? 0 : words[current].length() - ovl.secondOffset - ovl.overlapLength;
                for (int i = 0; i < howMuchBack; ++i) {
                    curr = curr.parent;
                }
                for (int i = ovl == null ? 0 : ovl.overlapLength; i < words[ch].length(); ++i) {
                    curr = new AnswerNode(curr, words[ch].charAt(i));
                }
                restoreAnswer(words, overlaps, parents, ch, curr);
            }
        }
    }

    public static void solve(String[] words, PrintWriter out) {
        AnswerNode.cleanup();
        words = removeSubstrings(words);

        int n = words.length;
        @SuppressWarnings({"unchecked"})
        List<Overlap>[] overlaps = new List[n];
        Overlap[][] o2 = new Overlap[n][n];
        for (int i = 0; i < n; ++i) {
            overlaps[i] = new ArrayList<>();
        }
        for (int li = 0; li < n; ++li) {
            for (int ri = 0; ri < n; ++ri) {
                if (li != ri) {
                    Overlap o = Overlap.compute(words[li], words[ri], li, ri);
                    overlaps[li].add(o);
                    o2[li][ri] = o;
                }
            }
        }

        boolean[] used = new boolean[n];

        int[] tree = new int[n];
        Arrays.fill(tree, n);

        while (true) {
            Overlap theMax = null;
            for (int t = 0; t < n; ++t) {
                if (!used[t]) {
                    for (Overlap ch : overlaps[t]) {
                        if ((theMax == null || ch.overlapLength > theMax.overlapLength) && !used[ch.target]) {
                            theMax = ch;
                        }
                    }
                }
            }
            if (theMax == null) {
                break;
            }
            tree[theMax.target] = theMax.source;
            used[theMax.source] = true;
        }

        AnswerNode root = new AnswerNode();
        restoreAnswer(words, o2, tree, n, root);

        out.println(AnswerNode.allNodes.size());
        for (AnswerNode nd : AnswerNode.allNodes) {
            out.println(nd.parent == null ? "0" : nd.parent.id + " " + nd.ch);
        }
    }

    public static void main(String[] args) throws IOException {
        try (BufferedReader in = new BufferedReader(new FileReader("dictionary.in"));
             PrintWriter out = new PrintWriter("dictionary.out")) {
            int n = Integer.parseInt(in.readLine());
            String[] words = new String[n];
            for (int i = 0; i < n; ++i) {
                words[i] = in.readLine();
            }
            solve(words, out);
        }
    }
}
