题目:BZOJ2434.
题目大意:有三个操作:
1.加入一个字符.
2.删除一个字符.
3.将当前字符串记录下来.
设将所有记录下来的字符串标上标号
1
1
1~
n
n
n,给出一些询问,每次询问
(
x
,
y
)
(x,y)
(x,y)表示询问第
x
x
x个字符串在第
y
y
y个字符串中出现的次数.
1
≤
n
≤
1
0
5
1\leq n\leq 10^5
1≤n≤105.
这道题即使告诉了我是dfs序我也没想到离线…
首先这道题可以离线,所以考虑离线建出AC自动机.然后考虑遍历AC自动机,遍历到一个点给这个点加1,退出一个点就给这个点减1,当遍历到一个点是第y个串的结尾时,就回答所有询问(x,y).
考虑询问(x,y)如何求解,我们回忆fail树的意义,fail树上每一个节点的子树中的节点都是以这个节点为后缀的.再考虑我们要的询问,其实就是询问一个表示y串的节点到根之间有多少个节点可以通过跳fail指针跳到x.
所以我们处理询问(x,y)只需要处理在fail树上x的子树有多少个y串上的节点,这个用dfs序+树状数组就可以处理.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
#define m(a) memset(a,0,sizeof(a))
const int N=100000,C=26;
struct Trie{
int s[C],fail,fa;
}tr[N+9];
int cn,d[N+9];
vector<int> y[N+9];
void Build(char *c,int len){
tr[cn=0]=Trie();
int x=0,n=0;
for (int i=1;i<=len;++i)
switch (c[i]){
case 'B':
x=tr[x].fa;
break;
case 'P':
y[x].push_back(++n);
d[n]=x;
break;
default:
if (tr[x].s[c[i]-'a']) x=tr[x].s[c[i]-'a'];
else {
tr[x].s[c[i]-'a']=++cn;
tr[cn]=Trie();
tr[cn].fa=x;
x=cn;
}
}
}
struct side{
int y,next;
}e[N*2+9];
int lin[N+9],top;
void ins(int x,int y){
e[++top].y=y;
e[top].next=lin[x];
lin[x]=top;
}
queue<int> que;
void Get_fail(){
for (int i=0;i<C;++i)
if (tr[0].s[i]) que.push(tr[0].s[i]);
while (!que.empty()){
int x=que.front(),t;que.pop();
for (int i=0;i<C;++i)
if (tr[x].s[i]){
t=tr[x].fail;
while (t&&!tr[t].s[i]) t=tr[t].fail;
tr[tr[x].s[i]].fail=tr[t].s[i];
que.push(tr[x].s[i]);
}
}
for (int i=1;i<=cn;++i)
ins(tr[i].fail,i);
}
int dfn[N+9],cd,low[N+9];
void dfs_dfn(int x){
dfn[x]=++cd;
for (int i=lin[x];i;i=e[i].next)
dfs_dfn(e[i].y);
low[x]=cd;
}
int c[N+9];
void Add(int x,int v){for (;x<=cd;x+=x&-x) c[x]+=v;}
int Query(int x){int sum=0;for (;x;x-=x&-x) sum+=c[x];return sum;}
vector<int>q[N+9],id[N+9];
int ans[N+9];
void dfs_ans(int x){
Add(dfn[x],1);
int siz=y[x].size(),ss,t;
for (int i=0;i<siz;++i){
t=y[x][i];ss=q[t].size();
for (int j=0;j<ss;++j)
ans[id[t][j]]=Query(low[d[q[t][j]]])-Query(dfn[d[q[t][j]]]-1);
//一定要处理好串与节点间的关系啊
}
for (int i=0;i<C;++i)
if (tr[x].s[i]) dfs_ans(tr[x].s[i]);
Add(dfn[x],-1);
}
char s[N+9];
int n;
Abigail into(){
scanf("%s",s+1);
n=strlen(s+1);
Build(s,n);
scanf("%d",&n);
int x,y;
for (int i=1;i<=n;++i){
scanf("%d%d",&x,&y);
q[y].push_back(x);
id[y].push_back(i);
}
}
Abigail work(){
Get_fail();
dfs_dfn(0);
dfs_ans(0);
}
Abigail outo(){
for (int i=1;i<=n;++i)
printf("%d\n",ans[i]);
}
int main(){
into();
work();
outo();
return 0;
}