// Problema: Counting Patterns
// Descripcion: Dada una cadena de texto, responder queries rapidamente que digan cuantas veces se encuentra una cadena de texto dada en el texto original
// Juez Virtual: https://c...content-available-to-author-only...s.fi/problemset/task/2103
#include <bits/stdc++.h>
using namespace std;
// Construye el suffix array usando el algoritmo de doubling + counting sort.
// Devuelve un vector con las posiciones de los sufijos del string original (sin '$').
vector<int> construct_suffix_array(string& s) {
s += "$"; // sentinel más pequeño que cualquier otro carácter
int n = s.length();
int alphabet = max(256, n); // tamaño del contador (al menos 256 para caracteres)
vector<int> suffix_array(n), rank(n), cnt(alphabet);
// conteo inicial por carácter
for (int i = 0; i < n; i++) {
cnt[s[i]]++;
}
// prefijos acumulados para counting sort
for (int i = 1; i < alphabet; i++) {
cnt[i] += cnt[i - 1];
}
// construir SA ordenando por primer carácter
for (int i = 0; i < n; i++) {
suffix_array[--cnt[s[i]]] = i;
}
// asignar clases iniciales (rank) según carácter
rank[suffix_array[0]] = 0;
for (int i = 1; i < n; i++) {
if (s[suffix_array[i]] != s[suffix_array[i - 1]]) {
rank[suffix_array[i]] = rank[suffix_array[i - 1]] + 1;
}
else {
rank[suffix_array[i]] = rank[suffix_array[i - 1]];
}
}
vector<int> new_suffix_array(n), new_rank(n);
// bucle de doubling: longitudes 1,2,4,... hasta cubrir n
for (int k = 0; (1 << k) < n; k++) {
// desplazamos sufijos para ordenar por la segunda mitad (radix step)
for (int i = 0; i < n; i++) {
new_suffix_array[i] = (suffix_array[i] - (1 << k) + n) % n;
}
// volver a usar cnt para ordenar por la primera clave (rank)
fill(cnt.begin(), cnt.end(), 0);
for (int i = 0; i < n; i++) {
cnt[rank[new_suffix_array[i]]]++;
}
for (int i = 1; i < alphabet; i++) {
cnt[i] += cnt[i - 1];
}
for (int i = n - 1; i >= 0; i--) {
suffix_array[--cnt[rank[new_suffix_array[i]]]] = new_suffix_array[i];
}
// recalcular nuevas clases (ranks) basadas en pares
new_rank[suffix_array[0]] = 0;
for (int i = 1; i < n; i++) {
pair<int, int> prev = {rank[suffix_array[i - 1]], rank[(suffix_array[i - 1] + (1 << k)) % n]};
pair<int, int> cur = {rank[suffix_array[i]], rank[(suffix_array[i] + (1 << k)) % n]};
if (prev != cur) {
new_rank[suffix_array[i]] = new_rank[suffix_array[i - 1]] + 1;
}
else {
new_rank[suffix_array[i]] = new_rank[suffix_array[i - 1]];
}
}
swap(rank, new_rank); // actualizar ranks para la siguiente iteración
}
s.pop_back(); // quitar sentinel del string original
suffix_array.erase(suffix_array.begin()); // quitar la entrada correspondiente al '$'
return suffix_array;
}
int main() {
cin.tie(0);
ios_base::sync_with_stdio(0);
string s;
cin >> s;
int n = s.length();
vector<int> suffix_array = construct_suffix_array(s);
int q;
cin >> q;
// Para cada patrón, hacemos dos búsquedas binarias sobre el SA
while (q--) {
string t;
cin >> t;
int l = 0;
int r = n;
// búsqueda del límite superior (<= t)
while (r - l > 1) {
int m = (l + r) / 2;
// comparar prefijo del sufijo con t (aquí se copia con substr)
string suffix = s.substr(suffix_array[m], t.length());
if (suffix <= t)
l = m;
else
r = m;
}
int upper = l;
l = 0;
r = n;
// búsqueda del límite inferior (< t)
while (r - l > 1) {
int m = (l + r) / 2;
string suffix = s.substr(suffix_array[m], t.length());
if (suffix < t)
l = m;
else
r = m;
}
int lower = l;
// verificar coincidencias exactas en los extremos encontrados
string suffix_lower = s.substr(suffix_array[lower], t.length());
string suffix_upper = s.substr(suffix_array[upper], t.length());
if (suffix_lower == t) lower--;
if (suffix_upper != t) upper = 0;
int ans = max(0, upper - lower);
cout << ans << endl;
}
}