题意 : 回答第x个模式串在第y个模式串中出现了几次。数据范围\(\sum_n,\sum_m,q\leq10^5\)
显然可以离线,对于相同y的询问集中处理,暴跳fail的时候开个桶丢进去,最后把有用的提出来。
但是还是太慢了。
考虑问题本质:对于一组询问\(x,y\)实际上是在问属于串\(y\)的节点有多少\(fail\)边指向\(x\)
可以注意到每个点有且仅有一个\(fail\) 于是从这个点的\(fail\)向这个点连边
然后就是dfs序BIT维护
但是插入串串太慢了
我们考虑在原来的trie树上走,进入一个点时+1,离开时-1,避免了重复插入删除。
这样对于不同的\(x\)也能继续进行回答。
因为没特判没有关于落在这个点上的串的询问导致RE了一上午
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
const int N = 1e5 + 7;
int pcnt = 1, endp[N], ecnt, last[N];
struct trie {int son[26], vis[26], fail, fa, end, sum;} t[N];
struct graph {int next, to;} e[N*5];
inline void add(int u, int v) {e[++ecnt].next = last[u], e[ecnt].to = v, last[u] = ecnt;}
int xcnt;
inline void ins(char *ss) {
int lens = strlen(ss), p = 1;
for (int i = 0; i < lens; i++) {
if (ss[i] == 'B') p = t[p].fa;
else if (ss[i] == 'P') endp[++xcnt] = p, t[p].sum++, t[p].end = xcnt;
else {
if (!t[p].son[ss[i] - 'a']) t[p].son[ss[i] - 'a'] = ++pcnt, t[pcnt].fa = p;
p = t[p].son[ss[i] - 'a'];
}
}
}
inline void getfail() {
std :: queue<int> que;
t[1].fail = 1;
for (int i = 0; i < 26; i++) if (t[1].son[i])
que.push(t[1].son[i]), t[t[1].son[i]].fail = 1;
else t[1].son[i] = 1;
while (!que.empty()) {
int u = que.front(); que.pop();
for (int i = 0; i < 26; i++) if (t[u].son[i])
t[t[u].son[i]].fail = t[t[u].fail].son[i], que.push(t[u].son[i]);
else t[u].son[i] = t[t[u].fail].son[i];
}
}
int dfn[N], c[N*10], low[N];int cnt;
inline int lbt(int x) {return (x & (-x));}
inline void modify(int x, int k) {while(x <= cnt) c[x] += k, x += lbt(x);}
inline int getc(int x) {int res = 0;while(x) res += c[x], x -= lbt(x);return res;}
inline void dfs1(int x) {
dfn[x] = ++cnt;
for (int i = last[x]; i; i = e[i].next) dfs1(e[i].to);
low[x] = cnt;
}
struct ques {int x, y, id, ans;} q[N];
bool operator < (ques a, ques b) {return a.y < b.y;}
int lastans[N], sum[N];
char ss[N]; int n, ql[N], qr[N];
inline void dfs2(int x) {
modify(dfn[x], 1);
if (t[x].end && ql[t[x].end])
for (int i = ql[t[x].end]; i <= qr[t[x].end]; i++)
q[i].ans = getc(low[endp[q[i].x]]) - getc(dfn[endp[q[i].x]] - 1);
for (int i = 0; i < 26; i++) if (t[x].vis[i]) dfs2(t[x].vis[i]);
modify(dfn[x], -1);
}
int main() {
scanf("%s", ss), ins(ss), scanf ("%d", &n);
for (int i = 1; i <= pcnt; i++)for (int j = 0; j < 26; j++) t[i].vis[j] = t[i].son[j];
for (int i = 1; i <= n; i++) scanf ("%d%d", &q[i].x, &q[i].y), q[i].id = i;
std :: sort (&q[1], &q[n + 1]);getfail();
for (int i = 2; i <= pcnt; i++) add(t[i].fail, i); dfs1(1);
for (int i = 1, opt = 1; i <= n; i = opt) {
ql[q[i].y] = i; while(q[opt].y == q[i].y) opt++; qr[q[i].y] = opt - 1;
} dfs2(1);
for (int i = 1; i <= n; i++) lastans[q[i].id] = q[i].ans;
for (int i = 1; i <= n; i++) printf("%d\n", lastans[i]);
return 0;
}