#include <iostream>
#include <queue>
#include <assert.h>   
#include <vector>
#include <algorithm>
#include <time.h>
#include <numeric>
#include <string>
#include <cstring>
#include <stack>
#include <unordered_set>
#include <unordered_map>
#include <set>
#include <map>
#include <numeric>
#include <deque>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <array>
#include <cmath>
#include <cstdio>
using namespace std;

//#define double long double
//#define int int64_t
//#define int unsigned long long

#define ll int64_t
#define ld long double 
#define pi pair<int, int> 
#define pl pair<ll,ll>  
#define pd pair<ld,ld> 
#define str string  
#define mp make_pair
#define vi vector<int> 
#define vl vector<ll> 
#define vd vector<ld> 
#define vs vector<str> 
#define vpi vector<pi> 
#define vpl vector<pl> 
#define vpd vector<pd> 
#define si set<int> 
#define FF(i,j,n) for(signed i=j;i<=n;i++)  
#define DD(i,j,n) for(signed i=j;i>=n;i--) 
#define F(i,j,n) for(signed i=j;i<n;i++)   
#define D(i,j,n) for(signed i=j;i>n;i--) 
#define mem(a,b) memset(a,b,sizeof(a))
#define ndl cout << endl
#define pte(x) cout << (x) << endl
#define pts(x) cout << (x) << " "
#define ull unsigned long long 

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;


#define sz(x) (signed)x.size()
#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend() 
#define rsz resize
#define ins insert 
#define ft front() 
#define bk back() 
#define X first
#define Y second
#define pf push_front 
#define pb push_back
#define eb emplace_back 
#define lb lower_bound 
#define ub upper_bound 
#define IOS ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);

//math

const int mod = 1e9 + 7;

ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
int pct(int x) { return __builtin_popcount(x); } 
int bit(int x) { return 31-__builtin_clz(x); } // floor(log2(x)) 
int cdiv(int a, int b) { return a/b+!(a<0||a%b == 0); } // division of a by b rounded up, assumes b > 0 



void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
  cerr << to_string(h); if (sizeof...(t)) cerr << ", ";
  DBG(t...); }
#ifdef LOCAL 
#define dbg(...) cerr << "[" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#define HERE cout << "==========GOTHERE==========" << endl
#define SHOWVECTOR(v) {std::cerr << #v << "\t: ";for(const auto& xxx : v){std::cerr << xxx << " ";}std::cerr << "\n";}
#define SHOWVECTOR2(v) {std::cerr << #v << "\t:\n";for(const auto& xxx : v){for(const auto& yyy : xxx){std::cerr << yyy << " ";}std::cerr << "\n";}}
#define SHOWQUEUE(a) {auto tmp(a);std::cerr << #a << "\t: ";while(!tmp.empty()){std::cerr << tmp.front() << " ";tmp.pop();}std::cerr << "\n";}
#define SHOWSTACK(a) {auto tmp(a);std::cerr << #a << "\t: ";while(!tmp.empty()){std::cerr << tmp.top() << " ";tmp.pop();}std::cerr << "\n";}
#else
#define dbg(...) 42
#define HERE 42
#define SHOWVECTOR(v) 42
#define SHOWVECTOR2(v) 42
#define SHOWQUEUE(a) 42
#define SHOWSTACK(a) 42
#endif
//order_of_key: The number of items in a set that are strictly smaller than k
//find_by_order: It returns an iterator to the ith largest element


 /* ============== END OF HEADER ============== */





const int maxn = 1e5*3+20;

int n,_,q,k;
int m;
vi g[maxn];
int indeg[maxn];


void solve(){
	cin >> n >> m >> k;
	auto gen = [&](str curr) -> vs{
		vs ans;
		for(int i = 0; i < (1 << k); i++){
			str tmp = curr;
			F(j,0,k){
				if(i & (1 << j)) tmp[j] = '_';
			}
			ans.eb(tmp);
		}
		return ans;
	};

	auto check = [&](str p, str s) -> bool{
		bool ok = true;
		F(i,0,k){
			if(p[i] != '_' && p[i] != s[i]) ok = false;
		}
		return ok;
	};
	vs patr(n);
	vs ts(m);
	vi match(m);
	map<str, int> table;
	bool valid = true;
	F(i,0,n){
		cin >> patr[i];
		table[patr[i]] = i;
	}
	F(i,0,m){
		cin >> ts[i] >> match[i];
		match[i]--;
		if(!check(patr[match[i]], ts[i])) valid = false;
	}
	if(!valid){
		pte("NO");
		exit(0);
	}

	F(i,0,m){
		vs tos = gen(ts[i]);
		for(str s : tos){
			if(s == patr[match[i]]) continue;
			if(table.count(s)){
				g[match[i]].eb(table[s]);
				indeg[table[s]]++;
			}
		}
	}

	vi order;
	vi que;
	F(i,0,n){
		if(!indeg[i]) que.eb(i);
	}
	while(sz(que)){
		int x = que.bk;
		que.pop_back();
		order.eb(x);
		for(int to : g[x]){
			if(!(--indeg[to])) que.eb(to);
		}
	}
	if(sz(order) != n){
		pte("NO");
		exit(0);
	}else{
		pte("YES");
		for(int x : order){
			pts(x + 1);
		}
		ndl;
	}






}

signed main(){
  //clock_t t1 = clock();  
	IOS
	solve();
  
  //cout << "THE ALGORITHM TOOK: " << (clock() - t1) * 1.0 / CLOCKS_PER_SEC * 1000 << "ms"<< endl;
	return 0;
}