您的位置:首页 > 其它

BZOJ2434 [Noi2011]阿狸的打字机【AC自动机+dfs序+树状数组】

2015-04-24 09:56 465 查看
题意:给出阿狸的打字顺序(小写字母是写入,‘B'是删除,’P'是打印,此处产生新的字符串),给出多组询问,每次询问第x号字符串在第y号字符串中的出现次数。

学过AC自动机的都知道,自动机上串A在串B中的出现次数,就是fail树上以串A结尾节点为根的子树中,串B的节点个数。这题我们用离线的方法,以y为关键字排序,在fail树的dfs序上用树状数组维护节点个数。为什么要按y为关键字排序呢?忽略‘P'操作,你没发现它打印删除打印删除的,挺像树的入栈出栈序的么。。。然后按y排序,后面的串上节点个数,就是入栈出栈序的前缀和啊0.0。(怎么觉得描述出来乱乱的,不好意思,词穷词穷= =。)

算法流程:

1.根据输入建立AC自动机,把fail树搞出来。

2.将询问以y为关键字排序。

3.扫一遍输入的串,如果是小写字母,就在树状数组中把该点位置+1,如果是‘B',就把它删除的对应节点在树状数组中-1,如果是’P',在树状数组中截取x的一段区间即是答案。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bitset>
#include<queue>
#include<vector>
#define ll long long
#define N 100010
#define INF 0x3f3f3f3f
using namespace std;
char str
;
int m;
int tr
[30],g
,id,pnt
,len;
int end
,begin
,in
,out
,_index=0;
vector<int> e
;
int ans
,r
;
queue<int> q;
struct node{
int a,b;
int id;
node(){}
node(int x,int y){a=x;b=y;}
friend bool operator < (node x,node y){
return x.b==y.b ? x.a<y.a : x.b<y.b;
}
}que
;
void build(){
pnt[1]=0;
int x=1;
for(int i=0;i<len;i++){
if(str[i]=='B'){
x=pnt[x];
}
else if(str[i]=='P'){
id++;
end[id]=x;
}
else{
if(!tr[x][str[i]-'a']) {
tr[x][str[i]-'a']=i+2;
pnt[i+2]=x;
}
x=tr[x][str[i]-'a'];
}
}
}
void init(){
gets(str);
len=strlen(str);
build();
scanf("%d",&m);
for(int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
que[i].a=end[x];
que[i].b=end[y];
que[i].id=i;
}
}
void bfs(){
int j,y;
g[1]=0;
q.push(1);
while(q.size()){
int x=q.front();
q.pop();
for(int i=0;i<26;i++){
if(y=tr[x][i]){
for(j=g[x];j;j=g[j]) if(tr[j][i]) break;
if(j){
g[y]=tr[j][i];
e[tr[j][i]].push_back(y);
}
else{
g[y]=1;
e[1].push_back(y);
}
q.push(y);
}
}
}
}
void dfs(int u){
in[u]=++_index;
for(int i=0;i<e[u].size();i++) dfs(e[u][i]);
out[u]=++_index;
}
namespace BIT{
int c[N*2];
int lowbit(int x){ return x&(-x); }
void add(int x,int ad){
while(x<=_index){
c[x]+=ad;
x+=lowbit(x);
}
}
int sum(int x){
int res=0;
while(x){
res+=c[x];
x-=lowbit(x);
}
return res;
}
}
void print(){
int i,j=1,now=0;
sort(que+1,que+m+1);
for(i=0;i<len;i++){
if(str[i]=='B'){
BIT::add(in[now+2],-1);
now=pnt[now+2]-2;
}
else if(str[i]=='P');
else{
now=i;
BIT::add(in[now+2],1);
}
while(que[j].b-2==i) {
ans[que[j].id]=BIT::sum(out[que[j].a])-BIT::sum(in[que[j].a]-1);
j++;
}
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
int main(){
init();
bfs();
dfs(1);
print();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息