Files
python/TangDou/AcWing/AcAutomation/P2414.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

126 lines
3.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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