您的位置:首页 > 大数据 > 人工智能

bzoj 2434 fail tree+dfs序

2014-03-04 17:41 357 查看
  首先比较明显的是我们可以将字符串组建立ac自动机,那么对于询问s1字符串在s2字符串中出现的次数,就是在以s1结尾为根的fail tree中,子树有多少个节点是s2的节点,这样我们处理fail tree的dfs序,然后用BIT维护,但是如果只是在线处理询问的话会tle,因为每个询问需要将节点的每一位在BIT中都修改,那么我们就浪费了好多性质,因为对于好多字符串拥有较长的LCP,那么我们可以模拟建trie的过程在自动机上跑,每遇到一个添加的字符,就解决所有询问为某字符串在该字符串中出现的次数,这样就可以了。

/**************************************************************
Problem: 2434
User: BLADEVIL
Language: C++
Result: Accepted
Time:852 ms
Memory:39128 kb
****************************************************************/

//By BLADEVIL
#include <cstdio>
#include <cstring>
#define maxn 200010

using namespace std;

struct node{
int cnt,last,left,right;
node *child[30],*fail,*father;
node(){
cnt=last=left=right=0;
fail=father=NULL;
memset(child,0,sizeof child);
}
}nodepool[maxn],*totnode,*root,*que[maxn],*adr[maxn],*other[maxn],*adrans[maxn];
char c[maxn];
int len,tot,l,sum;
int pre[maxn],bit[maxn];
int ll,preans[maxn],otherans[maxn],lastans[maxn],sizeans[maxn];
int ans[maxn];

void add(int x,int y){
while (x<=sum){
bit[x]+=y;
x+=x&(-x);
}
}

int ask(int x){
int ans=0;
while (x){
ans+=bit[x];
x-=x&(-x);
}
return ans;
}

void connect(node *x,node *y){
pre[++l]=x->last;
x->last=l;
other[l]=y;
//printf("%d %d\n",x,y);
}

void connectans(int x,int y,int z){
preans[++l]=lastans[x];
lastans[x]=l;
otherans[l]=y;
sizeans[l]=z;
}

void build_trie(){
totnode=nodepool; root=totnode++;
scanf("%s",&c); len=strlen(c);
node *t=root;
for (int i=0;i<len;i++){
if (c[i]=='P') adrans[++tot]=t; else
if (c[i]=='B') t=t->father; else {
if (!t->child[c[i]-'a'])
t->child[c[i]-'a']=totnode++,t->child[c[i]-'a']->father=t;
t=t->child[c[i]-'a'];
adr[i]=t;
};
//printf("%d ",t);
}
//printf("\n");
//for (int i=0;i<len;i++) printf("%d ",adr[i]);
//for (node *i=nodepool;i!=totnode;i++) printf("%d %d\n",i,i->father);
}

void build_ac(){
int h=0,t=1;
que[1]=root; root->fail=root;
for (int i=0;i<26;i++) if (!root->child[i]) root->child[i]=root;
while (h<t){
node *v=que[++h];
for (int i=0;i<26;i++) if (v->child[i]&&v->child[i]!=root){
que[++t]=v->child[i];
node *u=v->fail;
que[t]->fail=u->child[i]!=que[t]?u->child[i]:root;
} else v->child[i]=v->fail->child[i];
}
//for (int i=1;i<=t;i++) printf("%d %d ",que[i],que[i]->fail); printf("\n");
//for (int i=1;i<=tot;i++) printf("%d ",adr[i]); printf("\n");
}

void dfs(node *x,node *fa){
//printf("%d %d %d\n",x,fa,sum);
x->left=++sum;
for (int p=x->last;p;p=pre[p]){
if (other[p]==fa) continue;
dfs(other[p],x);
}
x->right=sum;
}

/*void work(){
for (node *i=nodepool;i!=totnode;i++) if (i!=root) connect(i->fail,i);
dfs(root,NULL);
//for (node *i=nodepool;i!=totnode;i++) printf("%d %d %d %d\n",i,i->left,i->right,i->father);
int m;
scanf("%d",&m);
while (m--){
int x,y;
scanf("%d %d",&x,&y);
for (node *i=adr[y];i!=root;i=i->father) add(i->left,1);//printf("%d ",i->left);
//printf("%d %d",adr[x]->left,adr[x]->right);
//printf("%d ",ask(adr[x]->right));
printf("%d\n",ask(adr[x]->right)-ask(adr[x]->left-1));
for (node *i=adr[y];i!=root;i=i->father) add(i->left,-1);
}
}*/

void work(){
for (node *i=nodepool;i!=totnode;i++) if (i!=root) connect(i->fail,i);
dfs(root,NULL);
int m;
scanf("%d",&m);
for (int i=1;i<=m;i++){
int x,y;
scanf("%d%d",&x,&y);
connectans(y,x,i);
}
int stack[maxn],tot=0,ansy=0;
memset(stack,0,sizeof stack);
for (int i=0;i<len;i++){
if (c[i]=='P'){
ansy++;
for (int p=lastans[ansy];p;p=preans[p]){
ans[sizeans[p]]=ask(adrans[otherans[p]]->right)-ask(adrans[otherans[p]]->left-1);
}
} else
if (c[i]=='B') {
add(adr[stack[tot--]]->left,-1);
} else {
stack[++tot]=i;
add(adr[i]->left,1);
}
}
for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
}

int main(){
build_trie();
build_ac();
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: