首页 > 代码库 > AC日记——[Noi2011]阿狸的打字机 bzoj 2434
AC日记——[Noi2011]阿狸的打字机 bzoj 2434
2434
思路:
构建ac自动机;
抽离fail树;
根据字符串建立主席树;
在线处理询问;
询问x在y中出现多少次,等同于y有多少字母的fail能走到x;
1a,hahahahah;
代码:
#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define maxn 100005struct TreeNodeType { int lc,rc,dis;};struct TreeNodeType tree[maxn*21];int n,ch[maxn][26],ff[maxn],fail[maxn],tot;int bel[maxn],bel_[maxn],pn,pla[maxn],head[maxn];int E[maxn<<1],V[maxn<<1],cnt,id[maxn],end[maxn];int root[maxn],tot_,m,times[maxn],sta[maxn],top;char str[maxn];queue<int>que;inline void in(int &now){ char Cget=getchar();now=0; while(Cget>‘9‘||Cget<‘0‘) Cget=getchar(); while(Cget>=‘0‘&&Cget<=‘9‘) { now=now*10+Cget-‘0‘; Cget=getchar(); }}void dfs1(int now,int fa){ id[now]=++cnt; for(int i=head[now];i;i=E[i]) { if(V[i]==fa) continue; dfs1(V[i],now); } end[now]=cnt;}void tree_build(int &now,int l,int r){ now=++tot_; if(l==r) return ; int mid=l+r>>1; tree_build(tree[now].lc,l,mid); tree_build(tree[now].rc,mid+1,r);}void tree_add(int pre,int &now,int l,int r,int to){ now=++tot_; tree[now].dis=tree[pre].dis+1; if(l==r) return ; int mid=l+r>>1; if(to<=mid) tree_add(tree[pre].lc,tree[now].lc,l,mid,to),tree[now].rc=tree[pre].rc; else tree_add(tree[pre].rc,tree[now].rc,mid+1,r,to),tree[now].lc=tree[pre].lc;}int tree_query(int now,int l,int r,int ll,int rr){ if(l==ll&&rr==r) return tree[now].dis; int mid=l+r>>1; if(ll>mid) return tree_query(tree[now].rc,mid+1,r,ll,rr); else if(rr<=mid) return tree_query(tree[now].lc,l,mid,ll,rr); else return tree_query(tree[now].lc,l,mid,ll,mid)+tree_query(tree[now].rc,mid+1,r,mid+1,rr);}int main(){ scanf("%s",str),ff[1]=0,tot=1; int len=strlen(str),now=1,pos,temp;n=len; for(int i=0;i<len;i++) { if(str[i]==‘P‘) { bel[i]=now,pla[++pn]=now; continue; } if(str[i]==‘B‘) { now=ff[now]; bel[i]=now; continue; } pos=str[i]-‘a‘,bel_[i]=now; if(!ch[now][pos]) ch[now][pos]=++tot,ff[ch[now][pos]]=now; now=ch[now][pos],bel[i]=now; } que.push(1);int u,v; while(!que.empty()) { now=que.front(),que.pop(); for(int i=0;i<26;i++) { if(!ch[now][i]) continue; que.push(ch[now][i]); if(now==1) fail[ch[now][i]]=1; else { temp=fail[now]; while(temp) { if(ch[temp][i]) { fail[ch[now][i]]=ch[temp][i]; break; } temp=fail[temp]; } if(!temp) fail[ch[now][i]]=1; } u=ch[now][i],v=fail[ch[now][i]]; E[++cnt]=head[u],V[cnt]=v,head[u]=cnt; E[++cnt]=head[v],V[cnt]=u,head[v]=cnt; } } cnt=0,dfs1(1,0),tree_build(root[0],1,n),now=0,pn=0; for(int i=0;i<len;i++) { if(str[i]==‘B‘) top--; else if(str[i]==‘P‘) times[++pn]=sta[top]; else { tree_add(root[sta[top]],root[i+1],1,n,id[bel[i]]); sta[++top]=i+1; } } in(m); for(int i=1;i<=m;i++) { in(u),in(v); printf("%d\n",tree_query(root[times[v]],1,n,id[pla[u]],end[pla[u]])); } return 0;}
AC日记——[Noi2011]阿狸的打字机 bzoj 2434
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。