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;
}
}