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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}