You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.6 KiB

2 years ago
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define QWQ cout << "QwQ" << endl;
#define ll long long
#include <vector>
#include <queue>
#include <stack>
#include <map>
#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<int> d[N]; // fail指针树
vector<int> at[N]; // tire树上点是哪些串的结束。
vector<int> wen[N]; //这个点即y串有哪些问题。。.
vector<int> e[N]; //原来的树因为我BFS时将原来的trie树改成了trie图所以我需要记录最开始时的树。
queue<int> 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;
}