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

public class E {

    int B = 37;
    int P = 1000003;

    int n;
    List<List<Link>> t;
    char[] s;
    int h;
    int[] curh = new int[300000];
    int p;
    int pow;
    int cnt;

    class Link {
        int child;
        char[] s;

        Link(int child, char[] s) {
            this.child = child;
            this.s = s;
        }
    }

    void go(int v) {
        for (Link l : t.get(v)) {
            for (char ch : l.s) {
                curh[p] = ch - 'a';
                if (p > 0) curh[p] += curh[p - 1] * B;
                if (curh[p] >= P) curh[p] %= P;
                if (p >= s.length - 1) {
                    int th = curh[p];
                    if (p >= s.length) {
                        th -= (int) ((long) curh[p - s.length] * pow % P);
                        if (th < 0) th += P;
                    }
                    if (h == th) {
                        ++cnt;
                    }
                }
                ++p;
            }
            go(l.child);
            p -= l.s.length;
        }
    }

    void solve() throws IOException {
        in("__std"); out("__std");

        n = readInt();
        t = new ArrayList<List<Link>>();
        for (int i = 0; i < n; ++i) {
            t.add(new ArrayList<Link>());
        }
        for (int i = 0; i < n - 1; ++i) {
            int p = readInt() - 1;
            t.get(p).add(new Link(i + 1, readToken().toCharArray()));
        }
        s = readLine().toCharArray();
        pow = 1;
        for (char ch : s) {
            h = (h * B + ch - 'a') % P;
            pow = pow * B % P;
        }
        go(0);
        println(cnt);

        exit();
    }

    void in(String name) throws IOException {
        if (name.equals("__std")) {
            in = new BufferedReader(new InputStreamReader(System.in));
        } else {
            in = new BufferedReader(new FileReader(name));
        }
    }

    void out(String name) throws IOException {
        if (name.equals("__std")) {
            out = new PrintWriter(System.out);
        } else {
            out = new PrintWriter(name);
        }
    }

    void exit() {
        out.close();
        System.exit(0);
    }

    char readChar() throws IOException {
        return (char) in.read();
    }

    int readInt() throws IOException {
        return Integer.parseInt(readToken());
    }

    long readLong() throws IOException {
        return Long.parseLong(readToken());
    }

    double readDouble() throws IOException {
        return Double.parseDouble(readToken());
    }

    String readLine() throws IOException {
        st = null;
        return in.readLine();
    }

    String readToken() throws IOException {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

    boolean eof() throws IOException {
        return !in.ready();
    }

    void print(String format, Object ... args) {
        out.print(new Formatter(Locale.US).format(format, args));
    }

    void println(String format, Object ... args) {
        out.println(new Formatter(Locale.US).format(format, args));
    }

    void print(Object value) {
        out.print(value);
    }

    void println(Object value) {
        out.println(value);
    }

    void println() {
        out.println();
    }

    StringTokenizer st;

    BufferedReader in;
    PrintWriter out;

    public static void main(String[] args) throws IOException {
        new E().solve();
    }
}


import java.io.*;

import java.awt.geom.Point2D;
import java.text.*;
import java.math.*;
import java.util.*;

public class Main implements Runnable {

	final String filename = "";

	public void solve() throws Exception {
		int N = iread();
		pos = new int[N];
		Arrays.fill(pos, -1);
		pos[0] = 0;
		par = new int[N];
		ss = new String[N];
		for (int i = 1; i < N; i++) {
			par[i] = iread() - 1;
			ss[i] = readword();
		}

		String s = readword();
		m = s.length();
		next = new int[26 * (m + 1)];

		int[] pi = new int[m];
		for (int i = 1; i < m; ++i) {
			int j = pi[i - 1];
			while (j > 0 && s.charAt(i) != s.charAt(j))
				j = pi[j - 1];
			if (s.charAt(i) == s.charAt(j))
				++j;
			pi[i] = j;
		}
		next[s.charAt(0) - 'a'] = 1;
		for (int i = 1; i <= m; i++) {
			for (int j = 0; j < 26; j++)
				next[i * 26 + j] = next[pi[i - 1] * 26 + j];
			if (i < m)
				next[i * 26 + s.charAt(i) - 'a'] = i + 1;
		}
		ans = 0;
		for (int i = 1; i < N; i++)
			dfs(i);
		out.write(ans + "\n");
	}

	void dfs(int x) {
		if (pos[x] != -1)
			return;
		dfs(par[x]);
		int cur = pos[par[x]];
		for (int i = 0; i < ss[x].length(); i++) {
			cur = next[cur * 26 + ss[x].charAt(i) - 'a'];
			if (cur == m) {
				ans++;
			}
		}
		pos[x] = cur;
	}

	int ans;
	int[] pos, par;
	String[] ss;

	int m;
	int[] next;

	public void run() {
		try {
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new BufferedWriter(new OutputStreamWriter(System.out));
			// in = new BufferedReader(new FileReader(filename+".in"));
			// out = new BufferedWriter(new FileWriter(filename+".out"));
			solve();
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
			System.exit(1);
		}
	}

	public int iread() throws Exception {
		return Integer.parseInt(readword());
	}

	public double dread() throws Exception {
		return Double.parseDouble(readword());
	}

	public long lread() throws Exception {
		return Long.parseLong(readword());
	}

	BufferedReader in;

	BufferedWriter out;

	public String readword() throws IOException {
		StringBuilder b = new StringBuilder();
		int c;
		c = in.read();
		while (c >= 0 && c <= ' ')
			c = in.read();
		if (c < 0)
			return "";
		while (c > ' ') {
			b.append((char) c);
			c = in.read();
		}
		return b.toString();
	}

	public static void main(String[] args) {
		try {
			Locale.setDefault(Locale.US);
		} catch (Exception e) {

		}
		// new Thread(new Main()).start();
		new Thread(null, new Main(), "1", 1 << 25).start();
	}
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.List;

public class E291
{

    static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static PrintWriter out = new PrintWriter(System.out);

    static int nextInt() throws Exception {
        in.nextToken();
        return (int)in.nval;
    }

    static String nextString() throws Exception {
        in.nextToken();
        return in.sval;
    }

    public static void main(String[] args) throws Exception {
        n = nextInt();
        v = new char[n][];
        g = new List[n];
        for (int i = 0; i < n; i++) g[i] = new ArrayList<Integer>();
        for (int i = 1; i < n; i++) {
            int p = nextInt();
            g[p-1].add(i);
            v[i] = nextString().toCharArray();
        }
        s = (nextString() + "$").toCharArray();
        sp = prefix(s);
        zp = new int[1000000];
        out.println(go(0, 0));
        out.flush();
    }

    static int n;
    static char[][] v;
    static List<Integer>[] g;
    static char[] s;
    static int[] sp, zp;

    static int[] prefix(char[] s) {
        int[] res = new int[s.length];
        res[0] = -1;
        for (int i = 1; i < s.length; i++) {
            int p = res[i-1];
            while (true) {
                if (s[p+1] == s[i]) {
                    res[i] = p+1;
                    break;
                }
                else if (p == -1) {
                    res[i] = -1;
                    break;
                }
                else p = res[p];
            }
        }
        return res;
    }

    static long go(int u, int k) {
        int ans = 0;
        for (int w : g[u]) {
            int i = k;
            for (char c : v[w]) {
                int p = i == 0 ? -1 : zp[i-1];
                while (true) {
                    if (s[p+1] == c) {
                        zp[i] = p+1;
                        break;
                    }
                    else if (p == -1) {
                        zp[i] = -1;
                        break;
                    }
                    else p = sp[p];
                }
                if (zp[i] == s.length-2) ans++;
                i++;
            }
            ans += go(w, i);
        }
        return ans;
    }
}


import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Queue;
import java.util.Scanner;
import java.util.concurrent.ArrayBlockingQueue;

public class ProblemE {

	static class Edge {
		int to;
		String s;
		Edge(int t, String _s) {
			to = t;
			s = _s;
		}
	}

	static class State {
		int from;
		Edge edge;
		int idx;
		long hash;
		int cnt;
		State(int f, Edge e, int i, long h, int c) {
			from = f;
			edge = e;
			idx = i;
			hash = h;
			cnt = c;
		}
	}

	static final long Z = 1000000009;

	/**
	 * @param args
	 */
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		int n = in.nextInt();
		List<Edge>[] graph = new List[n];
		for (int i = 0 ; i < n ; i++) {
			graph[i] = new ArrayList<Edge>();
		}
		for (int i = 1 ; i < n ; i++) {
			int p = in.nextInt() - 1;
			int q = i;
			String l = in.next();
			graph[p].add(new Edge(q, l));
		}

		long hash = 0;
		String search = in.next();
		int len = search.length();
		for (int i = 0 ; i < len ; i++) {
			hash *= Z;
			hash += search.charAt(i);
		}
		long del_n1 = 1;
		for (int i = 0 ; i < len ; i++) {
			del_n1 *= Z;
		}

		int[][] dist = new int[20][n];
		int[][] parent = new int[20][n];
		String[] ps = new String[n];
		for (int i = 0 ; i < 20 ; i++) {
			Arrays.fill(dist[i], -1);
			Arrays.fill(parent[i], -1);
		}
		for (int i = 0 ; i < n ; i++) {
			for (Edge e : graph[i]) {
				parent[0][e.to] = i;
				dist[0][e.to] = e.s.length();
				ps[e.to] = e.s;
			}
		}

		for (int k = 1 ; k < 20 ; k++) {
			for (int i = 0 ; i < n ; i++) {
				if (parent[k-1][i] != -1) {
					parent[k][i] = parent[k-1][parent[k-1][i]];
					dist[k][i] = dist[k-1][i] + dist[k-1][parent[k-1][i]];
				}
			}
		}

		long ans = 0;
		Queue<State> q = new ArrayBlockingQueue<State>(1000000);
		q.add(new State(0, null, -1, 0, 0));
		while (q.size() >= 1) {
			State s = q.poll();
			long del = 0;
			if (s.cnt == len) {
				int now = s.from;
				int get = len;
				if (s.edge != null) {
					if (get > s.idx) {
						get -= s.idx;
					} else {
						now = s.edge.to;
						get += (s.edge.s.length() - s.idx);
					}
				} else {
					// get++;
				}
				for (int k = 19 ; k >= 0 ; k--) {
					if (parent[k][now] != -1 && dist[k][now] < get) {
						get -= dist[k][now];
						now = parent[k][now];
					}
				}
				del = del_n1 * ps[now].charAt(ps[now].length() - get);
//				if (s.edge != null) {
//					debug(s.from,s.edge.to,s.idx);
//				} else {
//					debug("*",s.from,now,get);
//					debug(ps[now]);
//				}
//				debug(ps[now].charAt(ps[now].length() - get));
			}
			if (s.edge == null) {
				int tc = Math.min(len, s.cnt+1);
				for (Edge e : graph[s.from]) {
					long th = s.hash * Z;
					th += e.s.charAt(0);
					th -= del;
					if (th == hash) {
						ans++;
					}
					q.add(new State(s.from, e, 1, th, tc));
				}
			} else {
				if (s.edge.s.length() == s.idx) {
					q.add(new State(s.edge.to, null, 0, s.hash, s.cnt));
				} else {
					int tc = Math.min(len, s.cnt+1);
					long th = s.hash * Z;
					th += s.edge.s.charAt(s.idx);
					th -= del;
					if (th == hash) {
						ans++;
					}
					q.add(new State(s.from, s.edge, s.idx+1, th, tc));
				}
			}
		}
		out.println(ans);
		out.flush();
	}

	public static void debug(Object... o) {
		System.err.println(Arrays.deepToString(o));
	}
}


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

//import java.math.*;

public class SolE implements Runnable {
	public static void main(String[] args) {
		new Thread(new SolE()).start();
	}

	@Override
	public void run() {
		br = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);
		solve();
		out.close();
	}

	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;
	boolean eof = false;

	String nextToken() {
		while (st == null || !st.hasMoreTokens()) {
			try {
				st = new StringTokenizer(br.readLine());
			} catch (Exception e) {
				eof = true;
				return "0";
			}
		}
		return st.nextToken();
	}

	int nextInt() {
		return Integer.parseInt(nextToken());
	}

	double nextDouble() {
		return Double.parseDouble(nextToken());
	}

	long nextLong() {
		return Long.parseLong(nextToken());
	}

	int HASH = 53;

	class Vertex {
//		Vertex par;
		ArrayList<Vertex> children = new ArrayList<Vertex>();
		int h;
		long hash;
//		char ch;
		Vertex lenPar;
	}

	Vertex root;

	ArrayList<Integer>[] G;

	ArrayList<Vertex> vertices = new ArrayList<Vertex>();

	void dfs1(int i, Vertex v) {
//		System.err.println((i + 1) + " " + v.h + " " + s[i]);
		for (char ch : s[i].toCharArray()) {
			Vertex nv = new Vertex();
//			nv.ch = ch;
			nv.hash = v.hash * HASH + ch;
			nv.h = v.h + 1;
//			nv.par = v;
			v.children.add(nv);
			vertices.add(nv);
			v = nv;
		}
		for (int j : G[i]) {
			dfs1(j, v);
		}
	}

	String[] s;

	long ans = 0;

	ArrayList<Vertex> stack = new ArrayList<Vertex>();

	void dfsPar(Vertex v, int len) {
		if (stack.size() >= len) {
			v.lenPar = stack.get(stack.size() - len);
		}
		stack.add(v);
		for (Vertex u : v.children) {
			dfsPar(u, len);
		}
		stack.remove(stack.size() - 1);
	}

	long pow(long a, int b) {
		long ret = 1;
		while (b > 0) {
			if (b % 2 == 1) {
				ret *= a;
			}
			a *= a;
			b /= 2;
		}
		return ret;
	}

	void solve() {
		int n = nextInt();
		G = new ArrayList[n];
		for (int i = 0; i < n; i++) {
			G[i] = new ArrayList<Integer>();
		}
		int[] p = new int[n];
		s = new String[n];
		s[0] = "";
		for (int i = 1; i < n; i++) {
			p[i] = nextInt() - 1;
			s[i] = nextToken();
			G[p[i]].add(i);
		}
		root = new Vertex();
		vertices.add(root);
		dfs1(0, root);
		String ss = nextToken();
		long hs = 0;
		for (char ch : ss.toCharArray()) {
			hs = hs * HASH + ch;
		}
		int len = ss.length();
		dfsPar(root, len);
		long mod = pow(HASH, len);
		for (Vertex v : vertices) {
			if (v.lenPar != null) {
				long hash = v.hash - v.lenPar.hash * mod;
				if (hash == hs) {
//					System.err.println(v.ch + " "+ v.h);
					ans++;
				}
			}
		}
		out.println(ans);
	}
}


//package croc2013.q;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.Queue;

public class E {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni();
		int[] par = new int[n];
		char[][] ss = new char[n][];
		par[0] = -1;
		for(int i = 1;i < n;i++){
			par[i] = ni()-1;
			ss[i] = ns().toCharArray();
		}
		char[] key = ns().toCharArray();
		int[] kmp = kmpTable(key);

		int[][] ch = parentToChildren(par);
		Queue<Integer> q = new ArrayDeque<Integer>();
		q.add(0);
		int[] pos = new int[n];
		Arrays.fill(pos, -1);
		pos[0] = 0;
		long ct = 0;
		while(!q.isEmpty()){
			int cur = q.poll();
			if(cur != 0){
				int p = pos[par[cur]];
				for(char c : ss[cur]){
					while(p >= 0 && key[p] != c)p = kmp[p];
					if(++p == key.length){
						ct++;
						p = kmp[p];
					}
				}
				pos[cur] = p;
			}
			for(int e : ch[cur]){
				q.add(e);
			}
		}
		out.println(ct);
	}

	public static int[][] parentToChildren(int[] parent)
	{
		int n = parent.length;
		int[] ct = new int[n];
		for(int i = 0;i < n;i++){
			if(parent[i] >= 0){
				ct[parent[i]]++;
			}
		}
		int[][] ret = new int[n][];
		for(int i = 0;i < n;i++){
			ret[i] = new int[ct[i]];
		}
		for(int i = 0;i < n;i++){
			if(parent[i] >= 0){
				ret[parent[i]][--ct[parent[i]]] = i;
			}
		}

		return ret;
	}

	public static int[] kmpTable(char[] str) {
		int n = str.length;
		int[] kmp = new int[n + 1];
		kmp[0] = -1;
		kmp[1] = 0;
		for(int i = 2, j = 0;i <= n;i++){
			while (j > 0 && str[i - 1] != str[j])
				j = kmp[j];
			kmp[i] = str[i - 1] == str[j] ? ++j : 0;
		}
		return kmp;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.List;
import java.util.StringTokenizer;

public class CrocQualificationTaskE implements Runnable {

	private class Node {

		public Node(int to, String str) {
			this.to = to;
			this.str = str;
		}

		public int getTo() {
			return to;
		}

		public String getStr() {
			return str;
		}

		private String str;
		private int to;
	}

	private class Tree {

		public Tree(int n) {
			childs = new List[n];
			for (int i = 0; i < n; ++i) {
				childs[i] = new ArrayList<Node>();
			}
			p = new int[MAX_SIZE];
		}

		public void addChild(int parentId, int childId, String str) {
			childs[parentId].add(new Node(childId, str));
		}

		public void algo(String t, PrintWriter out) {
			this.t = t;
			p[0] = 0;
			tLength = t.length()-1;
			for (int i = 1; i <= tLength; ++i) {
				process(i, t.charAt(i));
			}
			dfs(0, tLength+1);
			out.print(answer);
		}

		private void dfs(int father, int startPosition) {
			for (Node child: childs[father]) {
				String str = child.getStr();
				int length = str.length();
				for (int i = 0; i < length; ++i) {
					if (process(startPosition+i, str.charAt(i)) == tLength) {
						++answer;
					}
				}
				dfs(child.getTo(), startPosition + length);
			}
		}

		public int process(int position, char c) {
			int value = p[position - 1];
			while (value > 0 && c != t.charAt(value)) {
				value = p[value - 1];
			}
			return p[position] = c == t.charAt(value) ? 1 + value : value;
		}

		private int tLength;
		private String t;
		private int[] p;
		private int answer;
		private List<Node>[] childs;

		private static final int MAX_SIZE = 300002;
	}

	public void readData() {
		InputReader in = new InputReader(System.in);
		try {
			int n = in.nextInt();
			tree = new Tree(n);
			for (int i = 1; i < n; ++i) {
				int parentId = in.nextInt() - 1;
				tree.addChild(parentId, i, in.next());
			}
			t = in.next().concat("$");
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

	private Tree tree;
	private String t;

	@Override
	public void run() {
		readData();
		PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
		tree.algo(t, out);
		out.flush();
	}

	public static void main(String[] args) {
		new CrocQualificationTaskE().run();
	}

	private class InputReader {

		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public InputReader(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream));
			tokenizer = null;
		}

		public String next() throws IOException {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}
	}
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class E {
	static int L = 4*1000*100;
	static long M = 1000L*1000*1000+7;
	static long[] HC1 = new long[26];
	static long[] HC2 = new long[26];
	static long[] P2 = new long[L];
	static long two_inv = BigInteger.valueOf(2).modInverse(BigInteger.valueOf(M)).longValue();

	static long ht1 = 0;
	static long ht2 = 0;
	static long ans = 0;

	static char[][] S;
	static List<List<Integer>> C = new ArrayList<List<Integer>>();

	static class RollingHash {
		LinkedList<Character> old;
		LinkedList<Character> L;
		long h1;
		long h2;
		int len;
		public RollingHash(int len) {
			old = new LinkedList<Character>();
			L = new LinkedList<Character>();
			h1 = 0;
			h2 = 0;
			this.len = len;
		}
		public void remove_char() { //doesn't adjust hashes
			L.removeLast();
			if(!old.isEmpty())
				L.addFirst(old.removeLast());
		}
		public void add_char(char ch) {
			h1 = ADD(h1, MULT(P2[L.size()], HC1[ch-'a']));
			h2 = ADD(h2, MULT(P2[L.size()], HC2[ch-'a']));
			L.addLast(ch);
			if(L.size() == len+1) {
				old.addLast(L.removeFirst());
				int old_ch = old.getLast();
				h1 = ADD(h1, -HC1[old_ch-'a']);
				h2 = ADD(h2, -HC2[old_ch-'a']);
				h1 = MULT(h1, two_inv);
				h2 = MULT(h2, two_inv);
			}
			if(h1 == ht1 && h2 == ht2) ans++;
		}
	}

	static long ADD(long x, long y) { return (x+y+M)%M; }
	static long MULT(long x, long y) { return (x*y)%M; }
	static int i(String s) { return Integer.parseInt(s); }
	public static void main(String[] args) throws Exception {
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		Random R = new Random();
		for(int i=0; i<26; i++) {
			HC1[i] = R.nextLong() % M;
			HC2[i] = R.nextLong() % M;
		}

		int n = i(in.readLine());
		S = new char[n][];
		for(int i=0; i<n; i++)
			C.add(new ArrayList<Integer>());
		for(int i=1; i<n; i++) {
			String[] arr = in.readLine().split("\\s+");
			int p = i(arr[0])-1;
			S[i] = arr[1].toCharArray();
			C.get(p).add(i);
		}

		P2[0] = 1;
		for(int i=1; i<L; i++)
			P2[i] = (P2[i-1]*2)%M;
		char[] T = in.readLine().toCharArray();
		for(int i=0; i<T.length; i++) {
			ht1 = ADD(ht1, MULT(P2[i], HC1[T[i]-'a']));
			ht2 = ADD(ht2, MULT(P2[i], HC2[T[i]-'a']));
		}

		f(0, new RollingHash(T.length));
		System.out.println(ans);
	}

	static void f(int v, RollingHash path) {
		long oldh1 = path.h1;
		long oldh2 = path.h2;
		for(Integer x : C.get(v)) {
			for(int i=0; i<S[x].length; i++) {
				path.add_char(S[x][i]);
			}
			f(x, path);
			//rollback
			path.h1 = oldh1;
			path.h2 = oldh2;
			for(int i=0; i<S[x].length; i++)
				path.remove_char();
		}
	}
}


#include <bits/stdc++.h>

#define MAX_N 1000
#define MAX_CHAR 26

using namespace std;

bool a[MAX_CHAR + 1][MAX_CHAR + 1][MAX_CHAR + 1][2];

int n;

struct elem
{
    string s;
    string nume;
    char c;
    int i;
};

elem v[MAX_N + 1];

void readFile()
{
    cin >> n;

    string a, b;
    a.clear();
    b.clear();
    int i;
    for(i = 1; i <= n; i ++)
    {
        cin >> a >> b;
        v[i].s = a;
        v[i].c = b[0];
        //cout << "CITIT\n";

        v[i].i = i;
    }
}

struct cmp
{
    bool operator () (elem a, elem b)
    {
        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

bool c3(int a, int b)
{
    if(a < 1 || b < 1 || a > n || b > n)
        return 0;

    int i;
    for(i = 0; i < 3; i ++)
    {
        if(v[a].s[i] != v[b].s[i])
            return 0;
    }

    return 1;
}

struct cmpI
{
    bool operator () (elem a, elem b)
    {
        return a.i < b.i;
    }
};

void solve()
{
    sort(v + 1, v + n + 1, cmp());

    int i;
    int MAX = (int)'A';
    for(i = 1; i <= n; i ++)
    {
        v[i].nume.resize(3);

        int ok = 1;

        if(c3(i, i - 1) == 1 || c3(i, i + 1) == 1)
            ok = 0;

        string cr = v[i].s;
        if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] == 1)
            ok = 0;

        if(ok == 0)
        {
            char c = v[i].c;

            if(a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] == 1)
            {
                cout << "NO\n";

                exit(0);
            }

           // cout << cr[0] << "\n";

            a[cr[0] - MAX][cr[1] - MAX][c - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] = 1;
            a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = 1;

            v[i].nume[0] = cr[0];
            v[i].nume[1] = cr[1];
            v[i].nume[2] = c;
        }

        else
        {
            a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][1] = 1;

            v[i].nume[0] = cr[0];
            v[i].nume[1] = cr[1];
            v[i].nume[2] = cr[2];
        }
    }

    sort(v + 1, v + n + 1, cmpI());
}

void printFile()
{
    printf("YES\n");

    int i;
    for(i = 1; i <= n; i ++)
        cout << v[i].nume << "\n";
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}


#include <bits/stdc++.h>

#define MAX_N 1000
#define MAX_CHAR 26

using namespace std;

int a[MAX_CHAR + 1][MAX_CHAR + 1][MAX_CHAR + 1][2];

int n;

struct elem
{
    string s;
    string nume;
    char c;
    int i;
    int ok;
};

elem v[MAX_N + 1];

void readFile()
{
    cin >> n;

    string a, b;
    a.clear();
    b.clear();
    int i;
    for(i = 1; i <= n; i ++)
    {
        cin >> a >> b;
        v[i].s = a;
        v[i].c = b[0];
        //cout << "CITIT\n";

        v[i].i = i;
    }
}

struct cmp
{
    bool operator () (elem a, elem b)
    {
        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

bool c3(int a, int b)
{
    if(a < 1 || b < 1 || a > n || b > n)
        return 0;

    int i;
    for(i = 0; i < 3; i ++)
    {
        if(v[a].s[i] != v[b].s[i])
            return 0;
    }

    return 1;
}

struct cmpI
{
    bool operator () (elem a, elem b)
    {
        return a.i < b.i;
    }
};

struct cmp2
{
    bool operator() (elem a, elem b)
    {
        if(a.ok != b.ok)
            return a.ok == 0;

        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

void solve()
{
    sort(v + 1, v + n + 1, cmp());

    int i;
    int MAX = (int)'A';

    for(i = 1; i <= n; i ++)
    {
        v[i].ok = 1;

        if(c3(i, i - 1) == 1 || c3(i, i + 1) == 1)
            v[i].ok = 0;
    }

    sort(v + 1, v + n + 1, cmp2());

    for(i = 1; i <= n; i ++)
    {
     //   cout << v[i].s << " " << v[i].c << " " << v[i].ok << "\n";

        v[i].nume.resize(3);

        int ok = v[i].ok;

        string cr = v[i].s;
        if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] != 0)
            ok = 0;

        if(ok == 0)
        {
            char c = v[i].c;

            if(a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] != 0)
            {
                cout << "NO\n";

                exit(0);
            }

           // cout << cr[0] << "\n";

           if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] == 1)
           {
                cout << "NO\n";

                exit(0);
           }

            a[cr[0] - MAX][cr[1] - MAX][c - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] = 2;
            a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = 3;

            v[i].nume[0] = cr[0];
            v[i].nume[1] = cr[1];
            v[i].nume[2] = c;
        }

        else
        {
            a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][1] = 1;

            v[i].nume[0] = cr[0];
            v[i].nume[1] = cr[1];
            v[i].nume[2] = cr[2];
        }
    }

    sort(v + 1, v + n + 1, cmpI());
}

void printFile()
{
    printf("YES\n");

    int i;
    for(i = 1; i <= n; i ++)
        cout << v[i].nume << "\n";
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}


#include <bits/stdc++.h>

#define MAX_N 1000
#define MAX_CHAR 26

using namespace std;

int a[MAX_CHAR + 1][MAX_CHAR + 1][MAX_CHAR + 1][2];

int n;

struct elem
{
    string s;
    string nume;
    char c;
    int i;
    int ok;
};

elem v[MAX_N + 1];

void readFile()
{
    cin >> n;

    string a, b;
    a.clear();
    b.clear();
    int i;
    for(i = 1; i <= n; i ++)
    {
        cin >> a >> b;
        v[i].s = a;
        v[i].c = b[0];
        //cout << "CITIT\n";

        v[i].i = i;
    }
}

struct cmp
{
    bool operator () (elem a, elem b)
    {
        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

bool c3(int a, int b)
{
    if(a < 1 || b < 1 || a > n || b > n)
        return 0;

    int i;
    for(i = 0; i < 3; i ++)
    {
        if(v[a].s[i] != v[b].s[i])
            return 0;
    }

    return 1;
}

struct cmpI
{
    bool operator () (elem a, elem b)
    {
        return a.i < b.i;
    }
};

struct cmp2
{
    bool operator() (elem a, elem b)
    {
        if(a.ok != b.ok)
            return a.ok == 0;

        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

void solve()
{
    sort(v + 1, v + n + 1, cmp());

    int i;
    int MAX = (int)'A';

    for(i = 1; i <= n; i ++)
    {
        v[i].ok = 1;

        if(c3(i, i - 1) == 1 || c3(i, i + 1) == 1)
            v[i].ok = 0;
    }

    sort(v + 1, v + n + 1, cmp2());

    for(i = 1; i <= n; i ++)
    {
     //   cout << v[i].s << " " << v[i].c << " " << v[i].ok << "\n";

        v[i].nume.resize(3);

        int ok = v[i].ok;

        string cr = v[i].s;
        if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] != 0)
            ok = 0;

        if(ok == 0)
        {
            char c = v[i].c;

            if(a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] != 0)
            {
                cout << "NO\n";

                exit(0);
            }

           // cout << cr[0] << "\n";

           /*if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] == 1)
           {
                cout << "NO\n";

                exit(0);
           }*/

            a[cr[0] - MAX][cr[1] - MAX][c - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] = 2;
            a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = 3;

            v[i].nume[0] = cr[0];
            v[i].nume[1] = cr[1];
            v[i].nume[2] = c;
        }

        else
        {
            a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][1] = 1;

            v[i].nume[0] = cr[0];
            v[i].nume[1] = cr[1];
            v[i].nume[2] = cr[2];
        }
    }

    sort(v + 1, v + n + 1, cmpI());
}

void printFile()
{
    printf("YES\n");

    int i;
    for(i = 1; i <= n; i ++)
        cout << v[i].nume << "\n";
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}


#include <bits/stdc++.h>

#define MAX_N 1000
#define MAX_CHAR 26

using namespace std;

int a[MAX_CHAR + 1][MAX_CHAR + 1][MAX_CHAR + 1][2];

int n;

struct elem
{
    string s;
    string nume;
    char c;
    int i;
    int ok;
};

elem v[MAX_N + 1];

void readFile()
{
    cin >> n;

    string a, b;
    a.clear();
    b.clear();
    int i;
    for(i = 1; i <= n; i ++)
    {
        cin >> a >> b;
        v[i].s = a;
        v[i].c = b[0];
        //cout << "CITIT\n";

        v[i].i = i;
    }
}

struct cmp
{
    bool operator () (elem a, elem b)
    {
        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

bool c3(int a, int b)
{
    if(a < 1 || b < 1 || a > n || b > n)
        return 0;

    int i;
    for(i = 0; i < 3; i ++)
    {
        if(v[a].s[i] != v[b].s[i])
            return 0;
    }

    return 1;
}

struct cmpI
{
    bool operator () (elem a, elem b)
    {
        return a.i < b.i;
    }
};

struct cmp2
{
    bool operator() (elem a, elem b)
    {
        if(a.ok != b.ok)
            return a.ok == 0;

        int i;
        for(i = 0; i < 3; i ++)
        {
            if(a.s[i] < b.s[i])
                return 1;

            if(a.s[i] > b.s[i])
                return 0;
        }

        return 0;
    }
};

int knou, kvechi;

int vechi[MAX_N + 1];
int nou[MAX_N + 1];

void solve()
{
    sort(v + 1, v + n + 1, cmp());

    int i;
    int MAX = (int)'A';

    for(i = 1; i <= n; i ++)
    {
        v[i].ok = 1;

        if(c3(i, i - 1) == 1 || c3(i, i + 1) == 1)
            v[i].ok = 0;
    }

    sort(v + 1, v + n + 1, cmp2());

    int cate = n;
    int kvechi = n;
    for(i = 1; i <= n; i ++)
        vechi[i] = i;

    int j;
    while(cate > 0)
    {
        int change = 0;
        for(j = 1; j <= kvechi; j ++)
        {
         //   cout << v[i].s << " " << v[i].c << " " << v[i].ok << "\n";

            i = vechi[j];
            v[i].nume.resize(3);

            int ok = v[i].ok;

            string cr = v[i].s;
            if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] != 0)
                ok = 0;

            if(ok == 0)
            {
                change = 1;
                cate --;

                char c = v[i].c;

                if(a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] != 0)
                {
                    cout << "NO\n";

                    exit(0);
                }

               // cout << cr[0] << "\n";

               if(a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] == 1)
               {
                    cout << "NO\n";

                    exit(0);
               }

                a[cr[0] - MAX][cr[1] - MAX][c - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][c - MAX][1] = 2;
                a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = 3;

                v[i].nume[0] = cr[0];
                v[i].nume[1] = cr[1];
                v[i].nume[2] = c;
            }

            else
            {
                nou[++ knou] = i;
            }
        }

        if(change == 0)
        {
            for(j = 1; j <= knou; j ++)
            {
                i = nou[j];

                string cr = v[i].s;
                a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][0] = a[cr[0] - MAX][cr[1] - MAX][cr[2] - MAX][1] = 1;

                v[i].nume[0] = cr[0];
                v[i].nume[1] = cr[1];
                v[i].nume[2] = cr[2];
            }

            break;
        }

        kvechi = knou;
        knou = 0;

        for(i = 1; i <= kvechi; i ++)
            vechi[i] = nou[i];
    }

    sort(v + 1, v + n + 1, cmpI());
}

void printFile()
{
    printf("YES\n");

    int i;
    for(i = 1; i <= n; i ++)
        cout << v[i].nume << "\n";
}

int main()
{
    readFile();

    solve();

    printFile();

    return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <set>
#include <numeric>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <queue>
#include <numeric>
#include <iomanip>
#define ll long long
using namespace std;
const int MAXN=40000;
string s[MAXN][2];
map<string,int> mp;
vector<int> adj[MAXN*10];
int sccId[MAXN*5];
int disCovered[MAXN*5];
int sccNumber;
int vertexNumber;
int n,e;
stack<int> st;
int dfs(int here){
    int there;
    st.push(here);
    disCovered[here]=vertexNumber++;
    int ret=disCovered[here];
    for(int i=0;i<adj[here].size();i++){
        there=adj[here][i];
        if(disCovered[there]==-1)
            ret=min(dfs(there),ret);
        else if(sccId[there]==-1)
            ret=min(ret,disCovered[there]);
    }
    if(ret==disCovered[here]){
        while(true){
            int num=st.top();st.pop();
            sccId[num]=sccNumber;
            if(num==here)
                break;
        }
        sccNumber++;
    }
    return ret;
}
void dfsAll(){
    for(int i=0;i<4*n;i++)
        if(disCovered[i]==-1)
            dfs(i);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<2;j++){
            cin>>s[i][j];
        }
        s[i][0]=s[i][0].substr(0,3);
        s[i][1]=s[i][0].substr(0,2)+s[i][1][0];
    }
    memset(sccId,-1,sizeof(sccId));
    memset(disCovered,-1,sizeof(disCovered));
    sccNumber=0;vertexNumber=0;
    for(int i=0;i<n;i++){
        adj[i*4+1].push_back(i*4+2);
        adj[i*4+3].push_back(i*4);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i].push_back(4*j+2);
                    adj[4*i].push_back(4*j+1);
                }
                if(s[i][0]==s[j][1]){
                    adj[4*i].push_back(4*j+0);
                     adj[4*i].push_back(4*j+3);
                }
                if(s[i][1]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                     adj[4*i+2].push_back(4*j+1);
                }
                if(s[i][1]==s[j][1]){
                    adj[4*i+2].push_back(4*j+0);
                     adj[4*i+2].push_back(4*j+3);
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        //내가 만약 type2를 뽑아
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                    adj[4*i+2].push_back(4*j+1);

                }
            }
        }
    }
    dfsAll();
    for(int i=0;i<n;i++){
        if(sccId[i*4]==sccId[i*4+1] || sccId[i*4+2]==sccId[i*4+3]){
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES\n";
    for(int i=0;i<n;i++)
    {
        string ret;
        if(sccId[i*4]<sccId[i*4+1]){
            cout<<s[i][0]<<"\n";
        }
        else{
            cout<<s[i][1]<<"\n";
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <set>
#include <numeric>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <queue>
#include <numeric>
#include <iomanip>
#define ll long long
using namespace std;
const int MAXN=40000;
string s[MAXN][2];
map<string,int> mp;
vector<int> adj[MAXN*10];
int sccId[MAXN*5];
int disCovered[MAXN*5];
int sccNumber;
int vertexNumber;
int n,e;
stack<int> st;
int dfs(int here){
    int there;
    st.push(here);
    disCovered[here]=vertexNumber++;
    int ret=disCovered[here];
    for(int i=0;i<adj[here].size();i++){
        there=adj[here][i];
        if(disCovered[there]==-1)
            ret=min(dfs(there),ret);
        else if(sccId[there]==-1)
            ret=min(ret,disCovered[there]);
    }
    if(ret==disCovered[here]){
        while(true){
            int num=st.top();st.pop();
            sccId[num]=sccNumber;
            if(num==here)
                break;
        }
        sccNumber++;
    }
    return ret;
}
void dfsAll(){
    for(int i=0;i<4*n;i++)
        if(disCovered[i]==-1)
            dfs(i);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<2;j++){
            cin>>s[i][j];
        }
        s[i][0]=s[i][0].substr(0,3);
        s[i][1]=s[i][0].substr(0,2)+s[i][1][0];
    }
    memset(sccId,-1,sizeof(sccId));
    memset(disCovered,-1,sizeof(disCovered));
    sccNumber=0;vertexNumber=0;
    for(int i=0;i<n;i++){
        adj[i*4+1].push_back(i*4+2);
        adj[i*4+3].push_back(i*4);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i].push_back(4*j+2);
                    adj[4*i].push_back(4*j+1);
                }
                if(s[i][0]==s[j][1]){
                    adj[4*i].push_back(4*j+0);
                     adj[4*i].push_back(4*j+3);
                }
                if(s[i][1]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                     adj[4*i].push_back(4*j+1);
                }
                if(s[i][1]==s[j][1]){
                    adj[4*i+2].push_back(4*j+0);
                     adj[4*i].push_back(4*j+3);
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        //내가 만약 type2를 뽑아
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                    adj[4*i+2].push_back(4*j+1);

                }
            }
        }
    }
    dfsAll();
    for(int i=0;i<n;i++){
        if(sccId[i*4]==sccId[i*4+1] || sccId[i*4+2]==sccId[i*4+3]){
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES\n";
    for(int i=0;i<n;i++)
    {
        string ret;
        if(sccId[i*4]<sccId[i*4+1]){
            cout<<s[i][0]<<"\n";
        }
        else{
            cout<<s[i][1]<<"\n";
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <set>
#include <numeric>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <queue>
#include <numeric>
#include <iomanip>
#define ll long long
using namespace std;
const int MAXN=40000;
string s[MAXN][2];
map<string,int> mp;
vector<int> adj[MAXN*10];
int sccId[MAXN*5];
int disCovered[MAXN*5];
int sccNumber;
int vertexNumber;
int n,e;
stack<int> st;
int dfs(int here){
    int there;
    st.push(here);
    disCovered[here]=vertexNumber++;
    int ret=disCovered[here];
    for(int i=0;i<adj[here].size();i++){
        there=adj[here][i];
        if(disCovered[there]==-1)
            ret=min(dfs(there),ret);
        else if(sccId[there]==-1)
            ret=min(ret,disCovered[there]);
    }
    if(ret==disCovered[here]){
        while(true){
            int num=st.top();st.pop();
            sccId[num]=sccNumber;
            if(num==here)
                break;
        }
        sccNumber++;
    }
    return ret;
}
void dfsAll(){
    for(int i=0;i<4*n;i++)
        if(disCovered[i]==-1)
            dfs(i);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<2;j++){
            cin>>s[i][j];
        }
        s[i][0]=s[i][0].substr(0,3);
        s[i][1]=s[i][0].substr(0,2)+s[i][1][0];
    }
    memset(sccId,-1,sizeof(sccId));
    memset(disCovered,-1,sizeof(disCovered));
    sccNumber=0;vertexNumber=0;
    for(int i=0;i<n;i++){
        adj[i*4+1].push_back(i*4+2);
        adj[i*4+3].push_back(i*4);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i].push_back(4*j+2);
                    adj[4*i].push_back(4*j+1);
                }
                if(s[i][0]==s[j][1]){
                    adj[4*i].push_back(4*j+0);
                     adj[4*i].push_back(4*j+3);
                }
                if(s[i][1]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                     adj[4*i].push_back(4*j+1);
                }
                if(s[i][1]==s[j][1]){
                    adj[4*i+2].push_back(4*j+0);
                     adj[4*i].push_back(4*j+3);
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        //내가 만약 type2를 뽑아
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                    adj[4*i+2].push_back(4*j+1);
                }
            }
        }
    }
    dfsAll();
    for(int i=0;i<n;i++){
        if(sccId[i*4]==sccId[i*4+1] || sccId[i*4+2]==sccId[i*4+3]){
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES\n";
    for(int i=0;i<n;i++)
    {
        string ret;
        if(sccId[i*4]<sccId[i*4+1]){
            cout<<s[i][0]<<"\n";
        }
        else{
            cout<<s[i][1]<<"\n";
        }
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <set>
#include <numeric>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <stack>
#include <cstring>
#include <queue>
#include <numeric>
#include <iomanip>
#define ll long long
using namespace std;
const int MAXN=40000;
string s[MAXN][2];
map<string,int> mp;
vector<int> adj[MAXN*10];
int sccId[MAXN*5];
int disCovered[MAXN*5];
int sccNumber;
int vertexNumber;
int n,e;
stack<int> st;
int dfs(int here){
    int there;
    st.push(here);
    disCovered[here]=vertexNumber++;
    int ret=disCovered[here];
    for(int i=0;i<adj[here].size();i++){
        there=adj[here][i];
        if(disCovered[there]==-1)
            ret=min(dfs(there),ret);
        else if(sccId[there]==-1)
            ret=min(ret,disCovered[there]);
    }
    if(ret==disCovered[here]){
        while(true){
            int num=st.top();st.pop();
            sccId[num]=sccNumber;
            if(num==here)
                break;
        }
        sccNumber++;
    }
    return ret;
}
void dfsAll(){
    for(int i=0;i<4*n;i++)
        if(disCovered[i]==-1)
            dfs(i);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<2;j++){
            cin>>s[i][j];
        }
        s[i][0]=s[i][0].substr(0,3);
        s[i][1]=s[i][0].substr(0,2)+s[i][1][0];
    }
    memset(sccId,-1,sizeof(sccId));
    memset(disCovered,-1,sizeof(disCovered));
    sccNumber=0;vertexNumber=0;
    for(int i=0;i<n;i++){
        adj[i*4+1].push_back(i*4+2);
        adj[i*4+3].push_back(i*4);
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i].push_back(4*j+2);
                    adj[4*i].push_back(4*j+1);
                }
                if(s[i][0]==s[j][1]){
                    adj[4*i].push_back(4*j+0);
                    adj[4*i].push_back(4*j+3);
                }
                if(s[i][1]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                    adj[4*i+2].push_back(4*j+1);
                }
                if(s[i][1]==s[j][1]){
                    adj[4*i+2].push_back(4*j+0);
                    adj[4*i+2].push_back(4*j+3);
                }
            }
        }
    }
    for(int i=0;i<n;i++){
        //내가 만약 type2를 뽑아
        for(int j=0;j<n;j++){
            if(i!=j){
                if(s[i][0]==s[j][0]){
                    adj[4*i+2].push_back(4*j+2);
                    adj[4*i+2].push_back(4*j+1);
                }
            }
        }
    }
    dfsAll();
    for(int i=0;i<n;i++){
        if(sccId[i*4]==sccId[i*4+1] || sccId[i*4+2]==sccId[i*4+3]){
            cout<<"NO";
            return 0;
        }
    }
    cout<<"YES\n";
    for(int i=0;i<n;i++)
    {
        string ret;
        if(sccId[i*4]<sccId[i*4+1]){
            cout<<s[i][0]<<"\n";
        }
        else{
            cout<<s[i][1]<<"\n";
        }
    }
    return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<ctime>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define LL long long
#define FOR(i,a,b) for (int i=a;i<=b;i++)
#define FORD(i,a,b) for (int i=a;i>=b;i--)
using namespace std;
typedef pair<int,int> pa;
void getint(int &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
set<pair<string,string> > ma;
int n,a[100010][2],fa[100010],d[100010],ans[100010];
string s,t;
int getf(int x){
	if (fa[x]==x) return x;
	int t=fa[x];
	fa[x]=getf(t);
	d[x]^=d[t];
	return fa[x];
}
void pr(int x){
	putchar(x/26/26+'A');
	putchar(x%(26*26)/26+'A');
	putchar(x%26+'A');
	putchar('\n');
}
int main(){
	scanf("%d",&n);
//	FOR(i,1,n) ans[i]=1;
	FOR(i,1,n){
		cin>>s>>t;
	//	if (ma.find(mp(s,t))!=ma.end()){
	//		return puts("NO"),0;
	//	}
		ma.insert(mp(s,t));
		a[i][1]=(s[0]-'A')*26*26+(s[1]-'A')*26+(t[0]-'A');
		a[i][0]=(s[0]-'A')*26*26+(s[1]-'A')*26+(s[2]-'A');
	//	if (a[i][0]>a[i][1]) swap(a[i][0],a[i][1]);
	}
	FOR(i,1,n-1)
		FOR(j,i+1,n)
			if (a[i][0]==a[j][0]){
				if (a[i][1]==a[j][1]) return puts("NO"),0;
				else ans[i]=ans[j]=1;
			}
			/*
	FOR(i,1,n) fa[i]=i;
	FOR(i,1,n)
		FOR(j,1,i-1)
			if (a[i][0]==a[j][0] && a[i][1]==a[j][1]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]==d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]==d[j]);
				}
			}
			else if (a[i][0]==a[j][1] && a[i][1]==a[j][0]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]^d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]^d[j]);
				}
			}*/
	puts("YES");
//	FOR(i,1,n) getf(i),ans[i]=d[i];

	FOR(i,1,n) pr(a[i][ans[i]]);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<ctime>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define LL long long
#define FOR(i,a,b) for (int i=a;i<=b;i++)
#define FORD(i,a,b) for (int i=a;i>=b;i--)
using namespace std;
typedef pair<int,int> pa;
void getint(int &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
set<int > ma;
int n,a[100010][2],fa[100010],d[100010],ans[100010];
string s,t;
int getf(int x){
	if (fa[x]==x) return x;
	int t=fa[x];
	fa[x]=getf(t);
	d[x]^=d[t];
	return fa[x];
}
void pr(int x){
	putchar(x/26/26+'A');
	putchar(x%(26*26)/26+'A');
	putchar(x%26+'A');
	putchar('\n');
}
int main(){
	scanf("%d",&n);
//	FOR(i,1,n) ans[i]=1;
	FOR(i,1,n){
		cin>>s>>t;
	//	if (ma.find(mp(s,t))!=ma.end()){
	//		return puts("NO"),0;
	//	}
	//	ma.insert(mp(s,t));
		a[i][1]=(s[0]-'A')*26*26+(s[1]-'A')*26+(t[0]-'A');
		a[i][0]=(s[0]-'A')*26*26+(s[1]-'A')*26+(s[2]-'A');
	//	if (a[i][0]>a[i][1]) swap(a[i][0],a[i][1]);
	}
	FOR(i,1,n-1)
		FOR(j,i+1,n)
			if (a[i][0]==a[j][0]){
				if (a[i][1]==a[j][1]) return puts("NO"),0;
				else ans[i]=ans[j]=1;
			}
			/*
	FOR(i,1,n) fa[i]=i;
	FOR(i,1,n)
		FOR(j,1,i-1)
			if (a[i][0]==a[j][0] && a[i][1]==a[j][1]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]==d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]==d[j]);
				}
			}
			else if (a[i][0]==a[j][1] && a[i][1]==a[j][0]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]^d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]^d[j]);
				}
			}*/
	FOR(i,1,n)
		if (ans[i]==1){
			FOR(j,1,n)
				if (i!=j && a[j][ans[j]]==a[i][1]) ans[j]^=1;
		}

	FOR(i,1,n){
		if (ma.find(a[i][ans[i]])!=ma.end()) return puts("NO"),0;
		ma.insert(a[i][ans[i]]);
	}
	puts("YES");
//	FOR(i,1,n) getf(i),ans[i]=d[i];

	FOR(i,1,n) pr(a[i][ans[i]]);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<ctime>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define LL long long
#define FOR(i,a,b) for (int i=a;i<=b;i++)
#define FORD(i,a,b) for (int i=a;i>=b;i--)
using namespace std;
typedef pair<int,int> pa;
void getint(int &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
set<pair<string,string> > ma;
int n,a[100010][2],fa[100010],d[100010],ans[100010];
string s,t;
int getf(int x){
	if (fa[x]==x) return x;
	int t=fa[x];
	fa[x]=getf(t);
	d[x]^=d[t];
	return fa[x];
}
void pr(int x){
	putchar(x/26/26+'A');
	putchar(x%(26*26)/26+'A');
	putchar(x%26+'A');
	putchar('\n');
}
int main(){
	scanf("%d",&n);
	FOR(i,1,n) ans[i]=1;
	FOR(i,1,n){
		cin>>s>>t;
	//	if (ma.find(mp(s,t))!=ma.end()){
	//		return puts("NO"),0;
	//	}
		ma.insert(mp(s,t));
		a[i][1]=(s[0]-'A')*26*26+(s[1]-'A')*26+(t[0]-'A');
		a[i][0]=(s[0]-'A')*26*26+(s[1]-'A')*26+(s[2]-'A');
	//	if (a[i][0]>a[i][1]) swap(a[i][0],a[i][1]);
	}
	FOR(i,1,n-1)
		FOR(j,i+1,n)
			if (a[i][0]==a[j][0]){
				if (a[i][1]==a[j][1]) return puts("NO"),0;
				else ans[i]=ans[j]=1;
			}
			/*
	FOR(i,1,n) fa[i]=i;
	FOR(i,1,n)
		FOR(j,1,i-1)
			if (a[i][0]==a[j][0] && a[i][1]==a[j][1]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]==d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]==d[j]);
				}
			}
			else if (a[i][0]==a[j][1] && a[i][1]==a[j][0]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]^d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]^d[j]);
				}
			}*/
	puts("YES");
//	FOR(i,1,n) getf(i),ans[i]=d[i];

	FOR(i,1,n) pr(a[i][ans[i]]);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<ctime>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define LL long long
#define FOR(i,a,b) for (int i=a;i<=b;i++)
#define FORD(i,a,b) for (int i=a;i>=b;i--)
using namespace std;
typedef pair<int,int> pa;
void getint(int &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
set<int > ma;
int n,a[100010][2],fa[100010],d[100010],ans[100010];
string s,t;
int getf(int x){
	if (fa[x]==x) return x;
	int t=fa[x];
	fa[x]=getf(t);
	d[x]^=d[t];
	return fa[x];
}
void pr(int x){
	putchar(x/26/26+'A');
	putchar(x%(26*26)/26+'A');
	putchar(x%26+'A');
	putchar('\n');
}
void dfs(int x){
	FOR(i,1,n)
		if (ans[i]==0 && a[x][1]==a[i][0]){
			ans[i]=1;
			dfs(i);
		}
}
int main(){
	scanf("%d",&n);
//	FOR(i,1,n) ans[i]=1;
	FOR(i,1,n){
		cin>>s>>t;
	//	if (ma.find(mp(s,t))!=ma.end()){
	//		return puts("NO"),0;
	//	}
	//	ma.insert(mp(s,t));
		a[i][1]=(s[0]-'A')*26*26+(s[1]-'A')*26+(t[0]-'A');
		a[i][0]=(s[0]-'A')*26*26+(s[1]-'A')*26+(s[2]-'A');
	//	if (a[i][0]>a[i][1]) swap(a[i][0],a[i][1]);
	}
	FOR(i,1,n-1)
		FOR(j,i+1,n)
			if (a[i][0]==a[j][0]){
				if (a[i][1]==a[j][1]) return puts("NO"),0;
				else ans[i]=ans[j]=1;
			}
			/*
	FOR(i,1,n) fa[i]=i;
	FOR(i,1,n)
		FOR(j,1,i-1)
			if (a[i][0]==a[j][0] && a[i][1]==a[j][1]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]==d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]==d[j]);
				}
			}
			else if (a[i][0]==a[j][1] && a[i][1]==a[j][0]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]^d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]^d[j]);
				}
			}*/

	FOR(i,1,n)
		if (ans[i]==1) dfs(i);

	FOR(i,1,n){
		if (ma.find(a[i][ans[i]])!=ma.end()) return puts("NO"),0;
		ma.insert(a[i][ans[i]]);
	}
	puts("YES");
//	FOR(i,1,n) getf(i),ans[i]=d[i];

	FOR(i,1,n) pr(a[i][ans[i]]);
	return 0;
}


#include<cstdio>
#include<cstring>
#include<iostream>
#include<stdlib.h>
#include<ctime>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
#include<queue>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define LL long long
#define FOR(i,a,b) for (int i=a;i<=b;i++)
#define FORD(i,a,b) for (int i=a;i>=b;i--)
using namespace std;
typedef pair<int,int> pa;
void getint(int &v){
    char ch,fu=0;
    for(ch='*'; (ch<'0'||ch>'9')&&ch!='-'; ch=getchar());
    if(ch=='-') fu=1, ch=getchar();
    for(v=0; ch>='0'&&ch<='9'; ch=getchar()) v=v*10+ch-'0';
    if(fu) v=-v;
}
set<int > ma;
int n,a[100010][2],fa[100010],d[100010],ans[100010];
string s,t;
int getf(int x){
	if (fa[x]==x) return x;
	int t=fa[x];
	fa[x]=getf(t);
	d[x]^=d[t];
	return fa[x];
}
void pr(int x){
	putchar(x/26/26+'A');
	putchar(x%(26*26)/26+'A');
	putchar(x%26+'A');
	putchar('\n');
}
int main(){
	scanf("%d",&n);
//	FOR(i,1,n) ans[i]=1;
	FOR(i,1,n){
		cin>>s>>t;
	//	if (ma.find(mp(s,t))!=ma.end()){
	//		return puts("NO"),0;
	//	}
	//	ma.insert(mp(s,t));
		a[i][1]=(s[0]-'A')*26*26+(s[1]-'A')*26+(t[0]-'A');
		a[i][0]=(s[0]-'A')*26*26+(s[1]-'A')*26+(s[2]-'A');
	//	if (a[i][0]>a[i][1]) swap(a[i][0],a[i][1]);
	}
	FOR(i,1,n-1)
		FOR(j,i+1,n)
			if (a[i][0]==a[j][0]){
				if (a[i][1]==a[j][1]) return puts("NO"),0;
				else ans[i]=ans[j]=1;
			}
			/*
	FOR(i,1,n) fa[i]=i;
	FOR(i,1,n)
		FOR(j,1,i-1)
			if (a[i][0]==a[j][0] && a[i][1]==a[j][1]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]==d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]==d[j]);
				}
			}
			else if (a[i][0]==a[j][1] && a[i][1]==a[j][0]){
				int X=getf(i),Y=getf(j);
				if (X==Y){
					if (d[i]^d[j]) return puts("NO"),0;
				}
				else{
					fa[X]=Y;
					d[X]=(d[i]^d[j]);
				}
			}*/
	FOR(i,1,n)
		if (ans[i]==1){
			FOR(j,1,n)
				if (i!=j && ans[j]==0 && a[j][ans[j]]==a[i][1]) ans[j]^=1;
		}

	FOR(i,1,n){
		if (ma.find(a[i][ans[i]])!=ma.end()) return puts("NO"),0;
		ma.insert(a[i][ans[i]]);
	}
	puts("YES");
//	FOR(i,1,n) getf(i),ans[i]=d[i];

	FOR(i,1,n) pr(a[i][ans[i]]);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
#define present(m,v) (m.find(v)!=m.end())
#define INF 1e18
#define mod 1000000007
#define lim 1000001
#define sz(a) int(a.size())
#define all(x) (x).begin(), (x).end()
#define rep(i,n) for(i=0;i<n;i++)
#define forn(i,a,b) for(i=a;i<b;i++)

bool solve(vector<pair<ll,pair<ll,ll> > > &v, ll ind, vector<bool> &res,vector<bool> &res1,vector<bool> &allow, vector<ll> &ans)
{
    if(ind==v.size())
        return true;
    if(res[v[ind].ss.ff]==false && allow[v[ind].ss.ff]==false)
    {
        res[v[ind].ss.ff]=true;
        res1[v[ind].ss.ff]=true;
        allow[v[ind].ss.ff]=true;
        if(!solve(v,ind+1,res,res1,allow,ans))
        {
            res[v[ind].ss.ff]=false;
            res1[v[ind].ss.ff]=false;
            allow[v[ind].ss.ff]=false;
            if(res[v[ind].ss.ss]==true)
                return false;
            res[v[ind].ss.ss]=true;
            allow[v[ind].ss.ff]=true;
            if(solve(v,ind+1,res,res1,allow,ans))
            {
                ans[v[ind].ff]=v[ind].ss.ss;
                return true;
            }
            else
            {
                res[v[ind].ss.ss]=false;
                allow[v[ind].ss.ff]=false;
                return false;
            }
        }
        else
        {
            ans[v[ind].ff]=v[ind].ss.ff;
            return true;
        }
    }
    else
    {
        if(res[v[ind].ss.ss]==true)
            return false;
        if(res1[v[ind].ss.ff]==true)
            return false;
        res[v[ind].ss.ss]=true;
        bool var=allow[v[ind].ss.ff];
        allow[v[ind].ss.ff]=true;
        if(solve(v,ind+1,res,res1,allow,ans))
        {
            ans[v[ind].ff]=v[ind].ss.ss;
            return true;
        }
        else
        {
            res[v[ind].ss.ss]=false;
            allow[v[ind].ss.ff]=var;
            return false;
        }
    }
}

int main()
{
	ll n,i;
	string a,b;
	vector<string> st;
	cin>>n;
	vector<ll> ans(n,-1);
	vector<pair<ll,pair<ll,ll> > > temp;
	map<string,vector<pair<ll,pair<ll,ll> > > > m;
	map<string,vector<pair<ll,pair<ll,ll> > > >::iterator it;
	for(i=0;i<n;i++)
    {
        cin>>a>>b;
        st.pb(a);
        if(!present(m,a.substr(0,2)))
            m[a.substr(0,2)]=temp;
        m[a.substr(0,2)].pb(mp(i,mp(a[2],b[0])));
    }
    for(it=m.begin();it!=m.end();it++)
    {
        vector<bool> res(100,false);
        vector<bool> res1(100,false);
        vector<bool> allow(100,false);
        if(!solve(it->second,0,res,res1,allow,ans))
            break;
    }
    if(it==m.end())
    {
        cout<<"YES\n";
        for(i=0;i<n;i++)
            cout<<st[i].substr(0,2)<<(char)ans[i]<<endl;
    }
    else cout<<"NO";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
#define present(m,v) (m.find(v)!=m.end())
#define INF 1e18
#define mod 1000000007
#define lim 1000001
#define sz(a) int(a.size())
#define all(x) (x).begin(), (x).end()
#define rep(i,n) for(i=0;i<n;i++)
#define forn(i,a,b) for(i=a;i<b;i++)

bool solve(vector<pair<ll,pair<ll,ll> > > &v, ll ind, vector<bool> &res,vector<bool> &res1,vector<bool> &allow, vector<ll> &ans)
{
    if(ind==v.size())
        return true;
    if(res[v[ind].ss.ff]==false && allow[v[ind].ss.ff]==false)
    {
        res[v[ind].ss.ff]=true;
        res1[v[ind].ss.ff]=true;
        allow[v[ind].ss.ff]=true;
        if(!solve(v,ind+1,res,res1,allow,ans))
        {
            res[v[ind].ss.ff]=false;
            res1[v[ind].ss.ff]=false;
            allow[v[ind].ss.ff]=false;
            if(res[v[ind].ss.ss]==true)
                return false;
            res[v[ind].ss.ss]=true;
            allow[v[ind].ss.ff]=true;
            if(solve(v,ind+1,res,res1,allow,ans))
            {
                ans[v[ind].ff]=v[ind].ss.ss;
                return true;
            }
            else
            {
                res[v[ind].ss.ss]=false;
                allow[v[ind].ss.ff]=false;
                return false;
            }
        }
        else
        {
            ans[v[ind].ff]=v[ind].ss.ff;
            return true;
        }
    }
    else
    {
        if(res[v[ind].ss.ss]==true)
            return false;
        if(res1[v[ind].ss.ff]==true)
            return false;
        res[v[ind].ss.ss]=true;
        bool var=allow[v[ind].ss.ff];
        allow[v[ind].ss.ff]=true;
        if(solve(v,ind+1,res,res1,allow,ans))
        {
            ans[v[ind].ff]=v[ind].ss.ss;
            return true;
        }
        else
        {
            res[v[ind].ss.ss]=false;
            allow[v[ind].ss.ff]=false;
            return false;
        }
    }
}

int main()
{
	ll n,i;
	string a,b;
	vector<string> st;
	cin>>n;
	vector<ll> ans(n,-1);
	vector<pair<ll,pair<ll,ll> > > temp;
	map<string,vector<pair<ll,pair<ll,ll> > > > m;
	map<string,vector<pair<ll,pair<ll,ll> > > >::iterator it;
	for(i=0;i<n;i++)
    {
        cin>>a>>b;
        st.pb(a);
        if(!present(m,a.substr(0,2)))
            m[a.substr(0,2)]=temp;
        m[a.substr(0,2)].pb(mp(i,mp(a[2],b[0])));
    }
    for(it=m.begin();it!=m.end();it++)
    {
        vector<bool> res(100,false);
        vector<bool> res1(100,false);
        vector<bool> allow(100,false);
        if(!solve(it->second,0,res,res1,allow,ans))
            break;
    }
    if(it==m.end())
    {
        cout<<"YES\n";
        for(i=0;i<n;i++)
            cout<<st[i].substr(0,2)<<(char)ans[i]<<endl;
    }
    else cout<<"NO";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
#define present(m,v) (m.find(v)!=m.end())
#define INF 1e18
#define mod 1000000007
#define lim 1000001
#define sz(a) int(a.size())
#define all(x) (x).begin(), (x).end()
#define rep(i,n) for(i=0;i<n;i++)
#define forn(i,a,b) for(i=a;i<b;i++)

bool solve(vector<pair<ll,pair<ll,ll> > > &v, ll ind, vector<bool> &res,vector<bool> &res1, vector<ll> &ans)
{
    if(ind==v.size())
        return true;
    if(res[v[ind].ss.ff]==false && res1[v[ind].ss.ff]==false)
    {
        res[v[ind].ss.ff]=true;
        res1[v[ind].ss.ff]=true;
        if(!solve(v,ind+1,res,res1,ans))
        {
            res[v[ind].ss.ff]=false;
            res1[v[ind].ss.ff]=false;
            if(res[v[ind].ss.ss]==true)
                return false;
            res[v[ind].ss.ss]=true;
            res1[v[ind].ss.ff]=true;
            if(solve(v,ind+1,res,res1,ans))
            {
                ans[v[ind].ff]=v[ind].ss.ss;
                return true;
            }
            else
            {
                res[v[ind].ss.ss]=false;
                res1[v[ind].ss.ff]=false;
                return false;
            }
        }
        else
        {
            ans[v[ind].ff]=v[ind].ss.ff;
            return true;
        }
    }
    else
    {
        if(res[v[ind].ss.ss]==true)
                return false;
        if(res[v[ind].ss.ff]==true && res1[v[ind].ss.ff]==true)
            return false;
        res[v[ind].ss.ss]=true;
        res1[v[ind].ss.ff]=true;
        if(solve(v,ind+1,res,res1,ans))
        {
            ans[v[ind].ff]=v[ind].ss.ss;
            return true;
        }
        else
        {
            res[v[ind].ss.ss]=false;
            res1[v[ind].ss.ff]=false;
            return false;
        }
    }
}

int main()
{
	ll n,i;
	string a,b;
	vector<string> st;
	cin>>n;
	vector<ll> ans(n,-1);
	vector<pair<ll,pair<ll,ll> > > temp;
	map<string,vector<pair<ll,pair<ll,ll> > > > m;
	map<string,vector<pair<ll,pair<ll,ll> > > >::iterator it;
	for(i=0;i<n;i++)
    {
        cin>>a>>b;
        st.pb(a);
        if(!present(m,a.substr(0,2)))
            m[a.substr(0,2)]=temp;
        m[a.substr(0,2)].pb(mp(i,mp(a[2],b[0])));
    }
    for(it=m.begin();it!=m.end();it++)
    {
        vector<bool> res(100,false);
        vector<bool> res1(100,false);
        if(!solve(it->second,0,res,res1,ans))
            break;
    }
    if(it==m.end())
    {
        cout<<"YES\n";
        for(i=0;i<n;i++)
            cout<<st[i].substr(0,2)<<(char)ans[i]<<endl;
    }
    else cout<<"NO";
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
#define present(m,v) (m.find(v)!=m.end())
#define INF 1e18
#define mod 1000000007
#define lim 1000001
#define sz(a) int(a.size())
#define all(x) (x).begin(), (x).end()
#define rep(i,n) for(i=0;i<n;i++)
#define forn(i,a,b) for(i=a;i<b;i++)

bool solve(vector<pair<ll,pair<ll,ll> > > &v, ll ind, vector<bool> &res,vector<bool> &res1, vector<ll> &ans)
{
    if(ind==v.size())
        return true;
    if(res[v[ind].ss.ff]==false && res1[v[ind].ss.ff]==false)
    {
        res[v[ind].ss.ff]=true;
        res1[v[ind].ss.ff]=true;
        if(!solve(v,ind+1,res,res1,ans))
        {
            res[v[ind].ss.ff]=false;
            res1[v[ind].ss.ff]=false;
            if(res[v[ind].ss.ss]==true)
                return false;
            res[v[ind].ss.ss]=true;
            res1[v[ind].ss.ff]=true;
            if(solve(v,ind+1,res,res1,ans))
            {
                ans[v[ind].ff]=v[ind].ss.ss;
                return true;
            }
            else
            {
                res[v[ind].ss.ss]=false;
                res1[v[ind].ss.ff]=false;
                return false;
            }
        }
        else
        {
            ans[v[ind].ff]=v[ind].ss.ff;
            return true;
        }
    }
    else
    {
        if(res[v[ind].ss.ss]==true)
            return false;
        if(res[v[ind].ss.ff]==true && res1[v[ind].ss.ff]==true)
            return false;
        res[v[ind].ss.ss]=true;
        bool var=res1[v[ind].ss.ff];
        res1[v[ind].ss.ff]=true;
        if(solve(v,ind+1,res,res1,ans))
        {
            ans[v[ind].ff]=v[ind].ss.ss;
            return true;
        }
        else
        {
            res[v[ind].ss.ss]=false;
            res1[v[ind].ss.ff]=var;
            return false;
        }
    }
}

int main()
{
	ll n,i;
	string a,b;
	vector<string> st;
	cin>>n;
	vector<ll> ans(n,-1);
	vector<pair<ll,pair<ll,ll> > > temp;
	map<string,vector<pair<ll,pair<ll,ll> > > > m;
	map<string,vector<pair<ll,pair<ll,ll> > > >::iterator it;
	for(i=0;i<n;i++)
    {
        cin>>a>>b;
        st.pb(a);
        if(!present(m,a.substr(0,2)))
            m[a.substr(0,2)]=temp;
        m[a.substr(0,2)].pb(mp(i,mp(a[2],b[0])));
    }
    for(it=m.begin();it!=m.end();it++)
    {
        vector<bool> res(100,false);
        vector<bool> res1(100,false);
        if(!solve(it->second,0,res,res1,ans))
            break;
    }
    if(it==m.end())
    {
        cout<<"YES\n";
        for(i=0;i<n;i++)
            cout<<st[i].substr(0,2)<<(char)ans[i]<<endl;
    }
    else cout<<"NO";
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;

vvi adj;
vi sccId, dscv;
stack<int> st;
int sccCnt, vtxCnt;
int scc(int here) {
	int ret = dscv[here] = vtxCnt++;
	st.push(here);
	rep(i, adj[here].size()) {
		int there = adj[here][i];
		if (dscv[there] == -1)
			ret = min(ret, scc(there));
		else if (dscv[there] < dscv[here] && sccId[there] == -1)
			return min(ret, dscv[there]);
	}
	if (ret == dscv[here]) {
		while (true) {
			int t = st.top(); st.pop();
			sccId[t] = sccCnt;
			if (t == here) break;
		}
		++sccCnt;
	}
	return ret;
}
vi tarjanSCC() {
	sccId = dscv = vi(adj.size(), -1);
	sccCnt = vtxCnt = 0;
	rep(i, adj.size()) if (dscv[i] == -1) scc(i);
	return sccId;
}
set<int> ddSet;
void makeGraph(const vi& meetings) {
	int mtSize = meetings.size();
	adj.clear();
	adj.resize(mtSize * 2);
	// left 가 두개 이상 있는 놈들을 따로 기록
	map<int, int> mm;
	set<int> dd;
	for (int i = 0; i < mtSize; i += 2) {
		mm[meetings[i]]++;
	}
	for (int i = 0; i < mtSize; i += 2) {
		if (mm[meetings[i]] > 1)
			ddSet.insert(i);	// 왼쪽이 같은게 두개 이상인 것들을 기록
	}
	for (int i = 0; i < mtSize; i += 2) {
		if (dd.count(i) > 1) {	// 왼쪽이 무조건 선택 안되는 경우 처리
			int j = i + 1;	// 오른쪽을 항상 참으로 : (!R U R) => R->!R, !R->R
			adj[j * 2].push_back(j * 2 + 1);
			adj[j * 2 + 1].push_back(j * 2);
		}
	}
	for (int i = 0; i < mtSize; i += 2) {
		if (dd.count(i) > 1) continue;	// 왼쪽은 무조건 선택 안함.
		int j = i + 1;
		adj[i * 2 + 1].push_back(j * 2);
		adj[j * 2 + 1].push_back(i * 2);
	}
	for (int i = 0; i < mtSize; ++i)
		for (int j = 0; j < i; ++j) {
			if (meetings[i] == meetings[j]) {
				adj[i * 2].push_back(j * 2 + 1);
				adj[j * 2].push_back(i * 2 + 1);
			}
		}
}
vi solve2SAT() {
	vi label = tarjanSCC();
	for (int i = 0; i < adj.size(); i += 2) if (label[i] == label[i + 1]) return vi();
	vpii order;
	for (int i = 0; i < adj.size(); ++i) order.push_back(mp(-label[i], i));
	sort(order.begin(), order.end());
	vi vbChoose(adj.size() / 2, -1); // 선택여부
	for (int i = 0; i < order.size(); ++i) {
		int node = order[i].second;
		int index = node / 2;
		if (ddSet.count(index)) {
			vbChoose[index] = false;
			vbChoose[index + 1] = true;
			continue;
		}
		if (vbChoose[index] != -1) continue;
		vbChoose[index] = !((node % 2) == 0);
	}
	return vbChoose;
}
vi solve(const vi& meetings) {
	makeGraph(meetings);
	vi ret = solve2SAT();
	return ret;
}
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	vi meetings(n * 2);
	map<string, int> my;
	map<int, string> myR;
	int index = 0;
	rep(i, n) {
		string str1, str2;	cin >> str1 >> str2;
		str1 = str1.substr(0, 3);
		str2 = str1.substr(0, 2) + str2[0];
		if (my.count(str1) == 0) {
			myR[index] = str1;  my[str1] = index++;
		}
		if (my.count(str2) == 0) {
			myR[index] = str2;	my[str2] = index++;
		}
		meetings[i * 2] = my[str1];
		meetings[i * 2 + 1] = my[str2];
	}
	vi value = solve(meetings);
	if (value.empty()) cout << "NO";
	else {
		cout << "YES" << '\n';
		for (int i = 0; i < 2 * n; i += 2) {
			if (value[i] == 1) {
				int idx = meetings[i];
				cout << myR[idx] << '\n';
			}
			else {
				int idx = meetings[i+1];
				cout << myR[idx] << '\n';
			}
		}
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;

const int N = 1010, M = 2020;
int n, m; bool adj[N][M];
vi aM, bM; vb vstd;
bool dfs(int a) {
	if (vstd[a]) return false;
	vstd[a] = true;
	for (int b = 0; b < m; ++b)
		if (adj[a][b])
			if (bM[b] == -1 || dfs(bM[b])) {
				aM[a] = b; bM[b] = a; return true;
			}
	return false;
}
int bpttM() {
	aM = vi(n, -1); bM = vi(m, -1);
	int size = 0;
	for (int start = 0; start < n; ++start) {
		vstd = vb(n, false);
		if (dfs(start)) ++size;
	}
	return size;
}
string arr[N][2];
map<string, int> cntF;
map<string, int> keyS;
map<int, string> valS;
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	cin >> n; m = n * 2;
	int idx = 0;
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		arr[i][0] = string{ str1[0], str1[1], str1[2] };
		arr[i][1] = string{ str1[0], str1[1], str2[0] };
		cntF[arr[i][0]]++;
		if (keyS.count(arr[i][0]) == 0)
			keyS[arr[i][0]] = idx, valS[idx] = arr[i][0], idx++;
		if (keyS.count(arr[i][1]) == 0)
			keyS[arr[i][1]] = idx, valS[idx] = arr[i][1], idx++;
	}
	rep(i, n) {
		int k1 = keyS[arr[i][0]], k2 = keyS[arr[i][1]];
		//if (cntF.count(arr[i][0]) == 1) // map 에선 count를 셀땐 최대 1...
		if (cntF[arr[i][0]] == 1)
			adj[i][k1] = 1;
		adj[i][k2] = 1;
	}
	int sz = bpttM();
	if (sz != n)
		//puts("NO");
		cout << "NO";
	else {
		//puts("YES");
		cout << "YES" << '\n';
		rep(i, aM.size()) {
			int b = aM[i];
			string str = valS[b];
			cout << str << '\n';
		}
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	map<pair<string, string>, int> my;
	bool ok = true;
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		str1 = str1.substr(0, 3);
		str2 = str1.substr(0, 2) + str2[0];
		pair<string, string> key = mp(str1, str2);
		if (my.count(key) == 0) my[key] = i;
		else {
			ok = false;
		}
	}
	if (ok == false) cout << "NO";
	else {
		//cout << "YES" << '\n';
		vs sol(n);
		string pre = "-1";
		map<pair<string, string>, int>::iterator it;
		it = my.begin();
		for (; it != my.end(); ++it) {
			string str1 = it->first.first;
			string str2 = it->first.second;
			int index = it->second;
			if (str2 == pre) {
				//cout << str2 << '\n';
				sol[index] = str1;
				pre = str1;
			}
			else {
				//cout << str1 << '\n';
				sol[index] = str2;
				pre = str2;
			}
		}
		vs sortSol = sol;
		sort(sortSol.begin(), sortSol.end());
		bool ok = true;
		pre = -1;
		rep(i, sortSol.size()) {
			if (sortSol[i] != pre)
				pre = sortSol[i];
			else {
				ok = false;
				break;
			}
		}
		if (ok == false)
			cout << "NO";
		else {
			cout << "YES" << "\n";
			rep(i, sol.size()) cout << sol[i] << '\n';
		}
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;

int main() {
	freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	map<pair<string, string>, int> my;
	bool ok = true;
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		str1 = str1.substr(0, 3);
		str2 = str1.substr(0, 2) + str2[0];
		pair<string, string> key = mp(str1, str2);
		if (my.count(key) == 0) my[key] = i;
		else {
			ok = false;
		}
	}
	if (ok == false) cout << "NO";
	else {
		cout << "YES" << '\n';
		vs sol(n);
		string pre = "-1";
		map<pair<string, string>, int>::iterator it;
		it = my.begin();
		for (; it != my.end(); ++it) {
			string str1 = it->first.first;
			string str2 = it->first.second;
			int index = it->second;
			if (str1 == pre) {
				//cout << str2 << '\n';
				sol[index] = str2;
				pre = str2;
			}
			else {
				//cout << str1 << '\n';
				sol[index] = str1;
				pre = str1;
			}
		}
		rep(i, sol.size()) cout << sol[i] << '\n';
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;
// 앞이 같은 놈이 존재시 뒤를 선택한다.
// 이때 뒤도 같으면 망한다.
// 또한 모든 선택된 것은 달라야 한다.
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	vector<pair<string, string>> arr(n);
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		arr[i].first = str1.substr(0, 3);
		arr[i].second = str1.substr(0, 2) + str2[0];
	}
	map<string, int> my, my2;
	rep(i, n) my[arr[i].first]++;
	vi choose(n, 0);
	rep(i, n) if (my[arr[i].first] > 1) {
		choose[i] = 1;	// 두번째꺼 선택
		my2[arr[i].second]++;	// 선택된거 기록
	}
	map<string, int>::iterator it = my2.begin();
	for (; it != my2.end(); ++it) if (it->second > 1) {
		cout << "NO"; return 0;
	}
	rep(i, n) {
		if (choose[i] == 1) continue;
		string key = arr[i].first;
		if (my2.count(key) > 0) {
			string key2 = arr[i].second;
			if (my2.count(key2) > 0) {
				cout << "NO"; return 0;
			}
			else {
				choose[i] = 1;
			//	my2[key2]++;
			}
		}
		else {
			//my2[key]++;
			choose[i] = 0;	// 굳이 할 필욘 없다.
		}
	}
	cout << "YES" << '\n';
	rep(i, choose.size()) {
		if (choose[i] == 0) cout << arr[i].first << '\n';
		else cout << arr[i].second << '\n';
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;
// 앞이 같은 놈이 존재시 뒤를 선택한다.
// 이때 뒤도 같으면 망한다.
// 또한 모든 선택된 것은 달라야 한다.

map<string, int> my, my2, my3;
vi choose;
vector<pair<string, string>> arr;
// 현 노드는 오른쪽 것만 선택해야 한다.
int dfs(int node) {
	if (choose[node] != 0) return 0;	// 이미 처리된거면 이상무
	string keyL = arr[node].first, keyR = arr[node].second;
	if (my2.count(keyL) > 0) {			// 연결된 놈이 있으면 keyR 을 선택해야 한다.
		if (my2.count(keyR) > 0)
			return -1;	// 선택 불가능한 경우
		my2[keyR]++;
		choose[node] = 2;	// 오른쪽이 선택된다.
		int nextNode = my3[keyR];	// keyR 을 왼쪽 키로 갖는 노드를 찾는다.
		if (nextNode == -1)
			return 0;
		return dfs(nextNode);
	}
	// 아무 노드에도 연결 된 것이 아니면 일단 무시한다.
	return 0;	// 이건 첫 호출에만 타는 루틴이 된다.
}
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	arr.resize(n);
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		arr[i].first = str1.substr(0, 3);
		arr[i].second = str1.substr(0, 2) + str2[0];
	}
	rep(i, n) my[arr[i].first]++;
	choose.resize(n, 0);
	rep(i, n) if (my[arr[i].first] > 1) {
		choose[i] = 2;	// 두번째꺼 선택
		my2[arr[i].second]++;	// 선택된거 기록
	}
	map<string, int>::iterator it = my2.begin();
	for (; it != my2.end(); ++it) if (it->second > 1) {
		cout << "NO"; return 0;
	}
	// left 가 유일한거 인덱스 기록
	rep(i, n) if (choose[i] != 2) my3[arr[i].first] = i;

	// 첫번째 키가 중복될 시 두번째 키를 선택하도록 한다. 그리고 dfs 탄다.
	rep(i, n) {
		if (choose[i] == 2) continue;
		string keyL = arr[i].first;
		if (my2.count(keyL) > 0) {	// 첫번째 키가 중복인 놈들로 dfs
			int node = my3[keyL];
			int judge = dfs(node);
			if (judge == -1) {
				cout << "NO"; return 0;
			}
		}
	}

	// 그다음 나머지들을 처리한다
	cout << "YES" << '\n';
	rep(i, choose.size()) {
		if (choose[i] == 0 || choose[i] == 1)
			cout << arr[i].first << '\n';
		else cout << arr[i].second << '\n';
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;

vvi adj;
vi sccId, dscv;
stack<int> st;
int sccCnt, vtxCnt;
int scc(int here) {
	int ret = dscv[here] = vtxCnt++;
	st.push(here);
	rep(i, adj[here].size()) {
		int there = adj[here][i];
		if (dscv[there] == -1)
			ret = min(ret, scc(there));
		else if (dscv[there] < dscv[here] && sccId[there] == -1)
			return min(ret, dscv[there]);
	}
	if (ret == dscv[here]) {
		while (true) {
			int t = st.top(); st.pop();
			sccId[t] = sccCnt;
			if (t == here) break;
		}
		++sccCnt;
	}
	return ret;
}
vi tarjanSCC() {
	sccId = dscv = vi(adj.size(), -1);
	sccCnt = vtxCnt = 0;
	rep(i, adj.size()) if (dscv[i] == -1) scc(i);
	return sccId;
}
set<int> ddSet;
void makeGraph(const vi& meetings) {
	int mtSize = meetings.size();
	adj.clear();
	adj.resize(mtSize * 2);
	// left 가 두개 이상 있는 놈들을 따로 기록
	map<int, int> mm;
	for (int i = 0; i < mtSize; i += 2) {
		mm[meetings[i]]++;
	}
	for (int i = 0; i < mtSize; i += 2) {
		if (mm[meetings[i]] > 1)
			ddSet.insert(i);	// 왼쪽이 같은게 두개 이상인 것들을 기록
	}

	set<int>::iterator it = ddSet.begin();
	for (; it != ddSet.end(); ++it) {
		int trueNode = *it * 2;
		int falseNode = *it * 2 + 1;
		adj[trueNode].push_back(falseNode);
	}
	for (int i = 0; i < mtSize; i += 2) {
		int j = i + 1;
		adj[i * 2 + 1].push_back(j * 2);
		adj[j * 2 + 1].push_back(i * 2);
	}
	for (int i = 0; i < mtSize; ++i)
		for (int j = 0; j < i; ++j) {
			if (meetings[i] == meetings[j]) {
				adj[i * 2].push_back(j * 2 + 1);
				adj[j * 2].push_back(i * 2 + 1);
			}
		}
}
vi solve2SAT() {
	vi label = tarjanSCC();
	for (int i = 0; i < adj.size(); i += 2) if (label[i] == label[i + 1]) return vi();
	vpii order;
	for (int i = 0; i < adj.size(); ++i) order.push_back(mp(-label[i], i));
	sort(order.begin(), order.end());
	vi vbChoose(adj.size() / 2, -1); // 선택여부
	for (int i = 0; i < order.size(); ++i) {
		int node = order[i].second;
		int index = node / 2;
		//if (ddSet.count(index)) {
		//	vbChoose[index] = false;
		//	vbChoose[index + 1] = true;
		//	continue;
		//}
		if (vbChoose[index] != -1) continue;
		vbChoose[index] = !((node % 2) == 0);
	}
	return vbChoose;
}
vi solve(const vi& meetings) {
	makeGraph(meetings);
	vi ret = solve2SAT();
	return ret;
}
int index;
map<string, int> my;
map<int, string> myR;
int getIndex(string& str) {
	if (my.count(str) == 0) {
		my[str] = index;
		myR[index] = str;
		index++;
	}
	return my[str];
}
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	vi meetings(n * 2);

	int index = 0;
	rep(i, n) {
		string str1, str2;	cin >> str1 >> str2;
		str1 = str1.substr(0, 3);
		str2 = str1.substr(0, 2) + str2[0];
		int idx1 = getIndex(str1);
		int idx2 = getIndex(str2);
		meetings[i * 2] = idx1;
		meetings[i * 2 + 1] = idx2;
	}
	vi value = solve(meetings);
	if (value.empty()) cout << "NO";
	else {
		cout << "YES" << '\n';
		for (int i = 0; i < 2 * n; i += 2) {
			if (value[i] == 1) {
				int idx = meetings[i];
				cout << myR[idx] << '\n';
			}
			else {
				int idx = meetings[i+1];
				cout << myR[idx] << '\n';
			}
		}
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	map<pair<string, string>, int> my;
	bool ok = true;
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		str1 = str1.substr(0, 3);
		str2 = str1.substr(0, 2) + str2[0];
		pair<string, string> key = mp(str1, str2);
		if (my.count(key) == 0) my[key] = i;
		else {
			ok = false;
		}
	}
	if (ok == false) cout << "NO";
	else {
		cout << "YES" << '\n';
		vs sol(n);
		string pre = "-1";
		map<pair<string, string>, int>::iterator it;
		it = my.begin();
		for (; it != my.end(); ++it) {
			string str1 = it->first.first;
			string str2 = it->first.second;
			int index = it->second;
			if (str2 == pre) {
				//cout << str2 << '\n';
				sol[index] = str1;
				pre = str1;
			}
			else {
				//cout << str1 << '\n';
				sol[index] = str2;
				pre = str2;
			}
		}
		rep(i, sol.size()) cout << sol[i] << '\n';
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;
// 앞이 같은 놈이 존재시 뒤를 선택한다.
// 이때 뒤도 같으면 망한다.
// 또한 모든 선택된 것은 달라야 한다.

map<string, int> my, my2, my3;
vi choose;
vector<pair<string, string>> arr;
// 현 노드는 오른쪽 것만 선택해야 한다.
int dfs(int node) {
	if (choose[node] != 0) return 0;	// 이미 처리된거면 이상무
	string keyL = arr[node].first, keyR = arr[node].second;
	if (my2.count(keyL) > 0) {			// 연결된 놈이 있으면 keyR 을 선택해야 한다.
		if (my2.count(keyR) > 0)
			return -1;	// 선택 불가능한 경우
		my2[keyR]++;
		choose[node] = 2;	// 오른쪽이 선택된다.
		int nextNode = my3[keyR];	// keyR 을 왼쪽 키로 갖는 노드를 찾는다.
		if (nextNode == -1)
			return 0;
		return dfs(nextNode);
	}
	// 아무 노드에도 연결 된 것이 아니면 일단 무시한다.
	return 0;	// 이건 첫 호출에만 타는 루틴이 된다.
}
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	arr.resize(n);
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		arr[i].first = str1.substr(0, 3);
		arr[i].second = str1.substr(0, 2) + str2[0];
	}
	rep(i, n) my[arr[i].first]++;
	choose.resize(n, 0);
	rep(i, n) if (my[arr[i].first] > 1) {
		choose[i] = 2;	// 두번째꺼 선택
		my2[arr[i].second]++;	// 선택된거 기록
	}
	map<string, int>::iterator it = my2.begin();
	for (; it != my2.end(); ++it) if (it->second > 1) {
		cout << "NO"; return 0;
	}
	// left 가 유일한거 인덱스 기록
	rep(i, n) if (choose[i] != 2) my3[arr[i].first] = i;

	// 첫번째 키가 중복될 시 두번째 키를 선택하도록 한다. 그리고 dfs 탄다.
	rep(i, n) {
		if (choose[i] == 2) continue;
		string keyL = arr[i].first;
		if (my2.count(keyL) > 0) {	// 첫번째 키가 중복
			string keyR = arr[i].second;
			int node = my3[keyR];
			int judge = dfs(node);
			if (judge == -1) {
				cout << "NO"; return 0;
			}
		}
	}

	// 그다음 나머지들을 처리한다
	cout << "YES" << '\n';
	rep(i, choose.size()) {
		if (choose[i] == 0 || choose[i] == 1)
			cout << arr[i].first << '\n';
		else cout << arr[i].second << '\n';
	}
	return 0;
}


#include <cstdio>
#include <queue>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <iomanip>
#include <limits>
#include <unordered_map>
#include <set>
#include <cmath>
#include <numeric> //accumulate
#include <stack>
#include <bitset>

//#include <unordered_set>//unordered_set

#define rep(i,a) for (int i = 0; i < (a); ++i)
#define rep2(i,a,b) for (int i = (a); i < (b); ++i)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define PI 3.14159265359;

	using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<double> vd;
typedef vector<string> vs;
typedef vector<pair<int, int>> vpii;
typedef vector<vector<int>> vvi;
typedef const vector<int> cvi;
typedef vector<bool> vb;

//const ll INF = 1ull << 62;
const int INF = 987654321;
const int MOD = 1000000007;
// 앞이 같은 놈이 존재시 뒤를 선택한다.
// 이때 뒤도 같으면 망한다.
// 또한 모든 선택된 것은 달라야 한다.
int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	int n; cin >> n;
	vector<pair<string, string>> arr(n);
	rep(i, n) {
		string str1, str2; cin >> str1 >> str2;
		arr[i].first = str1.substr(0, 3);
		arr[i].second = str1.substr(0, 2) + str2[0];
	}
	map<string, int> my, my2;
	rep(i, n) my[arr[i].first]++;
	vi choose(n, 0);
	rep(i, n) if (my[arr[i].first] > 1) {
		choose[i] = 1;	// 두번째꺼 선택
		my2[arr[i].second]++;	// 선택된거 기록
	}
	map<string, int>::iterator it = my2.begin();
	for (; it != my2.end(); ++it) if (it->second > 1) {
		cout << "NO"; return 0;
	}
	rep(i, n) {
		if (choose[i] == 1) continue;
		string key = arr[i].first;
		if (my2.count(key) > 0) {
			string key2 = arr[i].second;
			if (my2.count(key2) > 0) {
				cout << "NO"; return 0;
			}
			else {
				choose[i] = 1;
				my2[key2]++;
			}
		}
		else {
			//my2[key]++;
			choose[i] = 0;	// 굳이 할 필욘 없다.
		}
	}
	cout << "YES" << '\n';
	rep(i, choose.size()) {
		if (choose[i] == 0) cout << arr[i].first << '\n';
		else cout << arr[i].second << '\n';
	}
	return 0;
}