Prefix Function (KMP)

vector<int> pi(t.size());
for (int i = 1; i < (int) t.size(); i++) {
	int j = pi[i-1];
	while (j > 0 && t[i] != t[j]) j = pi[j - 1];
	if (t[i] == t[j]) j++;
	pi[i] = j;
}

Z-Function

template<typename T>
std::vector<int> buildZ(T const& v) {
	int n = v.size();
	std::vector<int> z(n);
	for (int i = 1, l = 0, r = 0; i < n; i++) {
		if (i <= r) z[i] = std::min(r - i + 1, z[i - l]);
		while(i + z[i] < n && v[z[i]+i] == v[z[i]]) z[i]++;
		if (z[i] + i - 1 > r) l = i, r = i + z[i] - 1;
	}
	return z;
}

Trie

struct Trie {
	map<char, Trie> mp;
	int cnt = 0; // qts string passaram aqui
	int end = 0; // qts strings terminaram aqui

	void add(string& s, int i = 0) {
		cnt++;
		if (i < (int) s.size()) {
			mp[s[i]].add(s, i + 1);
		} else end++;
	}
	
	void remove(string& s, int i = 0) {
    cnt--;
		if (i < (int) s.size()) {
			mp[s[i]].remove(s, i + 1);
		} else end--;
  }

  bool search(string& s, int i = 0) {
    if (i == (int) s.size()) return cnt > 0;
    if (mp.count(s[i])) return mp[s[i]].search(s, i + 1);
    return false;
  }
};
// utilizacao:
// Trie root;
// string s = "aab"; root.add(s);
// root.find(s); // true
struct Trie {
	int cnt = 0, end = 0;
	Trie* edges[26] = {};

	void add(string const& s, int i = 0) {
		cnt++;
		if (i == (int) s.size()) end++;
		else {
			int cur = s[i] - 'a';
			if (edges[cur] == nullptr) edges[cur] = new Trie();
			edges[cur]->add(s, i + 1);
		}
	}
};

// utilizacao:
// Trie* root = new Trie();
// string s = "aab"; root->add(s);

Hash

struct Hash { // double hash
	static constexpr int MOD[2] = {(int) 1e9+7, (int) 1e9+9};
	int val[2];

	Hash() { val[0] = val[1] = 0; }
	Hash(string const& s) { *this = calculateHash(s); }
	Hash(int x) { val[0] = x % MOD[0]; val[1] = x % MOD[1]; }
	Hash(int x, int y) { val[0] = x % MOD[0]; val[1] = y % MOD[1]; }

	inline static int add(int x, int y, int k) { x += y; if (x >= MOD[k]) x -= MOD[k]; return x; }
	inline static int sub(int x, int y, int k) { x -= y; if (x < 0) x += MOD[k]; return x; }
	inline static int mul(int x, int y, int k) { return 1ll * x * y % MOD[k]; }
	inline static int fpow(int x, int y, int k) {
		int r = 1;
		for (; y > 0; y /= 2, x = mul(x, x, k))
			if (y % 2 == 1) r = mul(r, x, k);
		return r;
	}
	inline static int divi(int x, int y, int k) { return mul(x, fpow(y, MOD[k] - 2, k), k); }
	inline static Hash pow(Hash x, int y) {
		Hash r = 1;
		for (; y >= 0; y /= 2, x *= x)
			if (y%2 == 1) r *= x;
		return r;
	}

	inline Hash operator+(Hash const& h) const { return Hash(add(val[0], h.val[0], 0), add(val[1], h.val[1], 1)); }
	inline Hash operator-(Hash const& h) const { return Hash(sub(val[0], h.val[0], 0), sub(val[1], h.val[1], 1)); }
	inline Hash operator*(Hash const& h) const { return Hash(mul(val[0], h.val[0], 0), mul(val[1], h.val[1], 1)); }
	inline Hash operator/(Hash const& h) const { return Hash(divi(val[0], h.val[0], 0), divi(val[1], h.val[1], 1)); }
	inline Hash& operator+=(Hash const& h) { return *this = *this + h; }
	inline Hash& operator-=(Hash const& h) { return *this = *this - h; }
	inline Hash& operator*=(Hash const& h) { return *this = *this * h; }
	inline Hash& operator/=(Hash const& h) { return *this = *this / h; }

	inline bool operator==(Hash const& h) const { return val[0] == h.val[0] && val[1] == h.val[1]; }
	inline bool operator!=(Hash const& h) const { return val[0] != h.val[0] || val[1] != h.val[1]; }

	inline static Hash calculateHash(string const& s, Hash const primes = Hash(31, 37)) {
		Hash cur = 0;
		Hash p = 1;
		for (char c : s) {
			cur += p * (c - 'a' + 1); // assuming that is a lowercase string
			p *= primes;
		}
		return cur;
	}
	inline static vector<Hash> calculateHashVector(string const& s, Hash const primes = Hash(31, 37)) {
		int n = s.size();
		Hash p = 1;
		vector<Hash> cur(n);
		for (int i = 0; i < n; i++) {
			if (i) cur[i] = cur[i-1];
			cur[i] += p * (s[i] - 'a' + 1);
			p *= primes;
		}
		return cur;
	}
	inline static vector<Hash> calculatePowerVector(Hash p, const int n) {
		vector<Hash> ans(n);
		ans[0] = 1;
		for (int i = 1; i < n; i++)
			ans[i] = ans[i-1] * p;
		return ans;
	}
	inline static Hash getRange(vector<Hash> const& v, vector<Hash> const& invPow, int l, int r) {
		return (v[r] - (l ? v[l-1] : 0)) * invPow[l];
	}
};

ostream& operator<<(ostream& out, Hash const& h) {
	return out << "[" << h.val[0] << "," << h.val[1] << "]";
}

#define hash UISHDUIAHSDU

/** NOTES:
 *    at the beginning, precalc:
 * 		vector<Hash> hash = Hash::calculateHashVector(s, primes);
 * 		vector<Hash> power = Hash::calculatePowerVector(primes, n);
 * 		vector<Hash> invPow = Hash::calculatePowerVector(Hash(1)/primes, n);
 * PS: you can code it much cleaner than it; the objective is just to code faster
 * */

Suffix Array

#include <bits/stdc++.h>

using namespace std;

namespace SuffixArray {

	// returns lcp array, with size a.size()-1, in which lcp[i] represents 
	// the longest common prefix between suffix in position i and the one in i+1
	// Complexidade: O(n)
	vector<int> build_lcp(vector<int> const& a, string const& s) {
		int n = a.size();
		vector<int> pos(n), lcp(n-1);
		for(int i = 0; i < n; ++i) {
			pos[a[i]] = i;
		}

		int sz = 0;
		for(int i = 0; i < n; ++i) {
			if(pos[i] == n-1) continue;
			int j = a[pos[i] + 1];
			while(i + sz < n and j + sz < n and s[i + sz] == s[j + sz]) sz++;
			lcp[pos[i]] = sz;
			if(sz) sz--;
		}
		return lcp;
	}

	// Retorna um vetor com os indices de inicio de prefixo.
	// Complexidade: O(n logn )
	vector<int> build_sufix_array(string s) {
		s += '$';
		int n = s.size();
		vector<int> head(n), a(n), a1(n), c(n), c1(n);

		iota(a.begin(), a.end(), 0);
		sort(a.begin(), a.end(), [&](int i, int j) {
			return s[i] < s[j];
		});

		int cc = 0;
		for(int i = 0; i < n; ++i) {
			if(i == 0 or s[a[i]] != s[a[i-1]]) {
				c[a[i]] = cc; 
				head[cc++] = i;
			} else c[a[i]] = c[a[i-1]];
		}

		int l = 1;
		while(l < n) {
			for(int i = 0; i < n; ++i) {
				int j = (a[i] - l + n)%n;
				a1[head[c[j]]++] = j;
			}
			cc = 0;

			head.assign(head.size(), 0);
			for(int i = 0; i < n; ++i) {
				if(i == 0 or c[a1[i]] != c[a1[i-1]] or c[(a1[i] + l)%n] != c[(a1[i-1] + l)%n]) {
					head[cc] = i;
					c1[a1[i]] = cc++;
				} else c1[a1[i]] = c1[a1[i-1]];
			}

			a = a1;
			c = c1;
			l <<= 1;
		}

		return a;
	}

};

Suffix Tree

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int N = 200007;

struct no {
	int l, r, par, suf;
	string * s;
	map<char, int> f;
	int len() {return r - l + 1;}
	char operator[](int i) {return (*s)[l+i];}
};

no t[N + N];

int new_node(int l, int r, int par, string * str) {
	static int ptr = 0;
	ptr++;
	t[ptr].l = l;
	t[ptr].r = r;
	t[ptr].par = par;
	t[ptr].s = str;
	return ptr;
}

void print_node(int u) {
	printf("Vert = %d\\t str = %s\\t par = %d\\n", u, (*t[u].s).substr(t[u].l, t[u].len()).c_str(), t[u].par);
}

void dfs(int u) {
	if(u) print_node(u);

	for(pair<char, int> g : t[u].f) {
		dfs(g.second);
	}
}

void build(string & s, int n) {
	int i, j, cn, cd, ns = 0;
	i = j = cn = cd = 0;

	t[0].r = -1;

	// invariante (cn, cd-1) representa a string S[i .. j-1]
	for(j = 0; j < n; ++j) {
		for(; i <= j; ++i) {
			if((cd == t[cn].len() and t[cn].f.count(s[j])) or (cd != t[cn].len() and t[cn][cd] == s[j])) { // se eh o caso 1
				// atualiza a invariante e vai pra proxima iteracao
				if(cd == t[cn].len()) {
					cn = t[cn].f[s[j]];
					cd = 0;
				} 
				cd++;
				break;
			} else if(cd == t[cn].len()) {
				t[cn].f[s[j]] = new_node(j, n-1, cn, &s); // como esse novo noh eh uma folha, seu r eh n-1 automaticamente
				if(cn) { // voce nao esta na raiz
					cn = t[cn].suf;
					cd = t[cn].len();
				}
			} else if(cd < t[cn].len()) { // caso = 3
				// Divide a aresta no meio, criando um novo noh interno e um novo noh folha
				int mid = new_node(t[cn].l, t[cn].l + cd - 1, t[cn].par, &s);
				t[t[mid].par].f[t[mid][0]] = mid;

				t[mid].f[s[j]] = new_node(j, n-1, mid, &s);
				t[mid].f[t[cn][cd]] = cn;
				t[cn].l += cd;
				t[cn].par = mid;
				if(ns) t[ns].suf = mid;
				

				// Parte 2
				cn = t[mid].par;
				int g; // g indica que o cn representa o cara s[i+1, g-1]. Quero atualizar cn ateh que g seja igual a j
				if(cn) {
					cn = t[cn].suf;
					g = j - cd;
				} else g = i+1;

				while(g < j and g + t[t[cn].f[s[g]]].len() <= j) {
					cn = t[cn].f[s[g]];
					g += t[cn].len();
				}
				if(g == j) {
					t[mid].suf = cn;
					cd = t[cn].len();
					ns = 0;
				} else {
					ns = mid;
					cn = t[cn].f[s[g]];
					cd = j - g;
				}
			}
		}
	}
}

bool find(string & s) {
	int cn, cd;
	cn = 0;
	cd = -1;

	for(int i = 0; i < s.size(); ++i) {
		char c = s[i];
		if(cd + 1 == t[cn].len()) {
			if(t[cn].f.count(c)) {
				cn = t[cn].f[c];
				cd = 0;
			} else return false;
		} else {
			if(c == t[cn][cd+1]) ++cd;
			else return false;
		}
	}

	return true;
}

int main() {
	string s;
	cin >> s;

	build(s, s.size());

	int q;
	cin >> q;

	dfs(0);

	for(int i = 0; i < q; ++i) {
		string str;
		cin >> str;

		if(find(str)) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
}