#include #include #include #include #include #define QWQ cout << "QwQ" << endl; #define ll long long #include #include #include #include #define ls now << 1 #define rs now << 1 | 1 using namespace std; const int N = 401010; const int qwq = 4003030; const int inf = 0x3f3f3f3f; int n, m; int cnt; char s[N]; struct T { int to[28], faith, from; } f[N]; // trie树 vector d[N]; // fail指针树 vector at[N]; // tire树上点是哪些串的结束。 vector wen[N]; //这个点(即y串)有哪些问题。。. vector e[N]; //原来的树,因为我BFS时将原来的trie树改成了trie图,所以我需要记录最开始时的树。 queue q; int wei[N]; //此字符串结束位置。 int askman[N], ans[N]; //此问题:谁发起问题(即x串),问题答案; int tree[qwq], id[N], siz[N]; void BFS() { for (int i = 1; i <= 26; i++) if (f[0].to[i]) q.push(f[0].to[i]); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = 1; i <= 26; i++) { int v = f[u].to[i]; if (v) { f[v].faith = f[f[u].faith].to[i]; q.push(v); } else f[u].to[i] = f[f[u].faith].to[i]; } } for (int i = 1; i <= cnt; i++) d[f[i].faith].push_back(i); //建fail树。 } void DFS1(int u) { //遍历fail树,算出每个点子树大小,并给每个点一个编号。 siz[u] = 1; id[u] = ++cnt; for (int i = 0; i < d[u].size(); i++) { int v = d[u][i]; DFS1(v); siz[u] += siz[v]; } } void insert(int now, int l, int r, int we, int g) { //单点修改 if (l == r) { tree[now] += g; return; } int mid = (l + r) >> 1; if (we <= mid) insert(ls, l, mid, we, g); else insert(rs, mid + 1, r, we, g); tree[now] = tree[ls] + tree[rs]; } int query(int now, int l, int r, int x, int y) { //区间查询 if (x <= l && r <= y) { return tree[now]; } int mid = l + r >> 1, res = 0; if (x <= mid) res += query(ls, l, mid, x, y); if (y > mid) res += query(rs, mid + 1, r, x, y); return res; } void TREE(int now) { //遍历原树 insert(1, 1, cnt, id[now], 1); //每到一个点就加上这个点的贡献 for (int i = 0; i < at[now].size(); i++) { int u = at[now][i]; for (int j = 0; j < wen[u].size(); j++) { int qu = wen[u][j], v = wei[askman[qu]]; // qu为问题编号,v为串x的结尾点 ans[qu] = query(1, 1, cnt, id[v], id[v] + siz[v] - 1); } } for (int i = 0; i < e[now].size(); i++) TREE(e[now][i]); insert(1, 1, cnt, id[now], -1); } int main() { int x, y; scanf("%s", s); int len = strlen(s), now = 0; for (int i = 0; i < len; i++) { int v = s[i] - 'a' + 1; if (s[i] == 'P') { at[now].push_back(++n); wei[n] = now; continue; } if (s[i] == 'B') { now = f[now].from; continue; } if (!f[now].to[v]) f[now].to[v] = ++cnt, e[now].push_back(f[now].to[v]); f[f[now].to[v]].from = now; now = f[now].to[v]; //涉及到退格,需要记录from。 } BFS(); cnt = 0; DFS1(0); scanf("%d", &m); for (int i = 1; i <= m; i++) { scanf("%d%d", &askman[i], &x); wen[x].push_back(i); } TREE(0); for (int i = 1; i <= m; i++) printf("%d\n", ans[i]); return 0; }