#include #include #include #include #include using namespace std; #define maxn 200000 #define clone Clone #define link Link int next[maxn * 2 + 10][26], len[maxn * 2 + 10], cnt[maxn * 2 + 10], link[maxn * 2 + 10], clone, j; int ls, sz, last, i, p, q, cur, n, k, l, node, x, y, occ, leng; pair sorter[maxn * 2 + 10]; char s[maxn + 5], c, a[maxn + 5]; vector vb[maxn + 1], ve[maxn + 1]; void build_sa () { // Suffix automaton building ls = strlen(s); sz = last = 1; for(i = 0; i < ls; i++) { c = s[i] - 'a'; len[cur = ++sz] = len[last] + 1; cnt[cur] = 1; for(p = last; p > 0 && !next[p][c]; p = link[p]) next[p][c] = cur; if (!p) link[cur] = 1; else { q = next[p][c]; if (len[p] + 1 == len[q]) link[cur] = q; else { len[clone = ++sz] = len[p] + 1; link[clone] = link[q]; for(j = 0; j < 26; j++) next[clone][j] = next[q][j]; for(; p && next[p][c] == q; p = link[p]) next[p][c] = clone; link[q] = link[cur] = clone; } } last = cur; } // For each node calculate the number of occurences of all substrigs, associated with it for(i = 1; i <= sz; i++) sorter[i] = make_pair(len[i], i); sort(sorter + 1, sorter + sz + 1); for(i = sz; i >= 1; i--) { k = sorter[i].second; cnt[link[k]] += cnt[k]; } // For each node calculate the lowest and the highest length of the substring, associated with it for(i = 1; i <= sz; i++) { y = len[i]; x = len[link[i]] + 1; // Now we have a segment parallel to Y-axis // Its' X-coordinate is cnt[i] // Its' Y-coordinates are len[i], len[link[i]] + 1 vb[cnt[i]].push_back(x); ve[cnt[i]].push_back(y + 1); } // We will use the binary search in future, so we need to sort our vectors for(i = 1; i <= ls; i++) { sort(vb[i].begin(), vb[i].end()); sort(ve[i].begin(), ve[i].end()); } } // How many numbers in the vector are not greater than k int count_not_greater (vector &a, int k) { if (!a.size()) return 0; int l = 0, r = a.size() - 1, mid; while (l < r) { mid = (l + r + 1) / 2; if (a[mid] > k) r = mid - 1; else l = mid; } if (a[l] > k) return 0; else return l + 1; } int main (int argc, char * const argv[]) { gets(s); build_sa(); scanf("%d", &n); for(i = 1; i <= n; i++) { // Now we read the query and answer it // We solve the problem in 1D case, so we do the same with what was written in the editorial scanf("%d %d", &leng, &occ); printf("%d\n", count_not_greater(vb[occ], leng) - count_not_greater(ve[occ], leng)); } return 0; }