#include <cassert>
#include <cstdint>
#include <iostream>
#include <map>
#include <string>
#include <tuple>
#include <unordered_map>
#include <utility>
#include <vector>

using namespace std;

/**
 * Consider the following algorithm: group all queries by their length and answer all of them at once.
 * For a fixed length, compute a hash of all substrings of that length. This takes O(n) time using a
 * rolling hash. Then find the k-th occurrence of the needed hash value.
 *
 * Let n = |s|. At first glance, this seems O(n^2). There are O(n) different
 * lengths t can take on, and each length takes O(n) time. However, because
 * there is a restriction on the length of the sum of t, there are actually
 * only O(sqrt(\sum |t|)) different values the length of t can take on. To see
 * this, consider a query string of length 1, then 2, then 3, and so on. The
 * total length grows quadratically.
 *
 * Therefore this algorithm runs in O(n * sqrt(\sum |t|)) time.
 */
template <int MOD>
struct modint {
    constexpr static int64_t fix(int64_t x) {
        x %= MOD;
        if (x < 0) x += MOD;
        return x;
    }

    int64_t v;
    constexpr modint(const int64_t _v = 0): v(fix(_v)) {}

    constexpr modint(const modint& other) {
        v = other.v;
    }

    // not generally useful, but good for maps?
    bool operator<(const modint& other) const { return v < other.v; }
    bool operator>(const modint& other) const { return v > other.v; }
    bool operator<=(const modint& other) const { return v <= other.v; }
    bool operator>=(const modint& other) const { return v >= other.v; }
    bool operator==(const modint& other) const { return v == other.v; }
    bool operator!=(const modint& other) const { return v != other.v; }

    modint& operator+=(const modint& other) {
        v += other.v;
        if (v >= MOD)
            v -= MOD;
        return *this;
    }

    modint& operator-=(const modint& other) {
        v -= other.v;
        if (v < 0)
            v += MOD;
        return *this;
    }

    modint& operator*=(const modint& other) {
        v = 1LL * v * other.v % MOD;
        return *this;
    }

    modint& operator/=(const modint& other) {
        *this *= other.inv();
        return *this;
    }

    modint operator+(const modint& other) const {
        return modint(v) += other;
    }

    modint operator-(const modint& other) const {
        return modint(v) -= other;
    }

    modint operator*(const modint& other) const {
        return modint(v) *= other;
    }

    modint operator/(const modint& other) const {
        return modint(v) /= other;
    }

    static modint pow(const modint& b, int64_t e) {
        modint res = 1;
        modint bb = b;
        for (int64_t p = 1; p <= e; p <<= 1) {
            if (e & p) {
                res *= bb;
            }

            bb *= bb;
        }

        return res;
    }

    modint pow(int64_t e) const {
        return pow(*this, e);
    }

    modint inv() const {
        return pow(MOD - 2);
    }

    friend istream& operator>>(istream& is, modint& m) {
        int64_t x;
        is >> x;

        m.v = fix(x);

        return is;
    }

    friend ostream& operator<<(ostream& os, const modint& m) {
        return os << m.v;
    }
};

using H = modint<1'000'000'007>;

namespace std {
    template <>
    struct hash<H> {
        size_t operator()(H v) const {
            return static_cast<size_t>(v.v);
        }
    };
}

// chosen by fair dice roll
// guaranteed to be random
constexpr static H B(97);

vector<H> rolling_hashes(const string& s, int len) {
    H pow = 1;
    for (int i = 0; i < len; ++i) {
        pow *= B;
    }

    vector<H> prefixes(s.size() + 1, 0);
    vector<H> res;

    res.reserve(s.size());
    for (int i = 0; i < s.size(); ++i) {
        prefixes[i + 1] = prefixes[i] * B + s[i];
        if (i + 1 >= len) {
            res.push_back(prefixes[i + 1] - prefixes[i + 1 - len] * pow);
        }
    }

    return res;
}

H rk_hash(const string& s) {
    vector<H> res = rolling_hashes(s, s.size());
    assert(res.size() == 1);

    return res[0];
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    string s;
    cin >> s;

    int n = s.size();

    int q;
    cin >> q;

    using query = tuple<H, int, int>;
    vector<vector<query>> queries(n);
    for (int i = 0; i < q; ++i) {
        string t;
        int k;
        cin >> t >> k;

        int len = t.size();
        --k;
        if (len <= queries.size()) {
            queries[len - 1].emplace_back(rk_hash(t), k, i);
        }
    }

    vector<int> ans(q, -1);

    // This looks O(n^2) but is actually O(n^1.5)
    for (int len = 0; len < n; ++len) {
        if (queries[len].empty()) {
            continue;
        }

        vector<H> hashes = rolling_hashes(s, len + 1);

        unordered_map<H, vector<int>> idxs;
        for (int i = 0; i < hashes.size(); ++i) {
            idxs[hashes[i]].push_back(i);
        }

        for (auto [t, k, idx] : queries[len]) {
            auto it = idxs.find(t);
            if (it != idxs.end() && it->second.size() > k) {
                // 1-indexing
                ans[idx] = it->second[k] + 1;
            }
        }
    }

    for (auto x : ans) {
        cout << x << '\n';
    }

    return 0;
}
