传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2434
思路:AC自动机,离线处理,主要利用fail树的性质,然而我犯傻了,dfs序总是犯晕,wa好多次,应该引起重视,再总结一下dfs序
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100000
using namespace std;
struct edge{int nxt,point,v;};
struct node { int x,y,ans,id;};
struct trie{ int judge,fa,a[26],fail; };
node ask[N + 5];
trie T[N + 5];
edge e[(N << 2) + 5];
char s[N + 5];
int m,num,cnt,s0[N + 5],id1[N + 5],st[N + 5],tt[N + 5],que[N + 5],l[N + 5],r[N + 5],top,c[N + 5];
inline bool cmp(node a,node b){ return (a.y < b.y); }
inline bool cmp1(node a,node b){ return (a.id < b.id); }
inline void addedge(int u1,int v1){ e[++cnt].nxt = e[u1].point; e[u1].point = cnt; e[cnt].v = v1;}
inline void insert(int u1,int v1){ addedge(u1,v1); addedge(v1,u1);}
inline int lowbit(int x) { return (x&(-x));}
inline void add(int posi,int x){ for (int i = posi;i <= top; i += lowbit(i)) c[i] += x;}
inline int query(int posi) {
int sum = 0;
for (int i = posi;i;i -= lowbit(i)) sum += c[i];
return sum;
}
inline int getnum(){
char c; int num;
while (!isdigit(c = getchar()));
num = c - '0';
while (isdigit(c = getchar())) num = 10 * num + c - '0';
return num;
}
void make_trie(){
int l = strlen(s + 1),q = 0;
num = 0; cnt = 0;
for (int i = 1;i <= l; ++i)
if (s[i] == 'P') s0[++num] = q,id1[q] = num,T[q].judge++;
else if (s[i] == 'B') q = T[q].fa;
else { int k = s[i] - 'a';
if (!T[q].a[k]) T[q].a[k] = ++cnt;
T[T[q].a[k]].fa = q;
q = T[q].a[k]; }
//cout<<cnt<<endl;
}
void init(){
scanf("%s",s + 1);
m = getnum();
make_trie();
for (int i = 1;i <= m; ++i) ask[i].x = getnum(),ask[i].y = getnum(),ask[i].id = i;
for (int i = 1;i <= m; ++i) ask[i].x = s0[ask[i].x],ask[i].y = s0[ask[i].y];
sort(ask + 1,ask + m + 1,cmp);
for (int i = 1;i <= m; ++i){
if (ask[i].y != ask[i - 1].y) st[ask[i].y] = i;
if (ask[i].y != ask[i + 1].y) tt[ask[i].y] = i; }
//for (int i = 1;i <= m; ++i) cout<<ask[i].x<<" "<<ask[i].y<<endl;
//for (int i = 1;i <= cnt; ++i) cout<<id1[i]<<endl;
//for (int i = 1;i <= num; ++i) cout<<s0[i]<<endl;
top = 0;
}
void make_ac(){
int head = 0,tail = 1; cnt = 0;
que[1] = 0;
while (head < tail){
int x = que[++head];
for (int i = 0;i < 26; ++i)
if (T[x].a[i])
{
que[++tail] = T[x].a[i];
if (x){
int q = T[x].fail;
while (q&&!T[q].a[i]) q = T[q].fail;
T[T[x].a[i]].fail = T[q].a[i];}
insert(T[x].a[i],T[T[x].a[i]].fail);
}
}
}
inline void dfs(int x){
l[x] = ++top;
for (int p = e[x].point;p;p = e[p].nxt)
if (!l[e[p].v]) dfs(e[p].v);
r[x] = top;
}
inline void dfs1(int x){
add(l[x],1);
if (T[x].judge)
for (int i = st[x];i <= tt[x]; ++i) ask[i].ans = query(r[ask[i].x]) - query(l[ask[i].x] - 1);
for (int i = 0;i < 26; ++i)
if (T[x].a[i]) dfs1(T[x].a[i]);
add(l[x],-1);
}
void DO_IT(){
make_ac();
//for (int i = 1;i <= 8; ++i) cout<<T[i].fail<<endl;
dfs(0);
dfs1(0);
}
void print(){
sort(ask + 1,ask + m + 1,cmp1);
for (int i = 1;i <= m; ++i) printf("%d\n",ask[i].ans);
}
int main(){
init();
DO_IT();
print();
return 0;
}