[bzoj2434] [Noi2011]阿狸的打字机
2016-06-28 14:07
489 查看
AC自动机+树状数组。
先把fail边反向建出fail树来。。
第x个字符串在第y个字符串中出现了多少次。对于y的每个前缀,如果它结尾可以通过fail跳到x的结尾的话,那么就出现了x。。
也就是查询x的fail子树中,有多少个y的节点。
在trie上暴力跑,在树状数组上加入根到当前节点路径上的点(将对应dfn值所在的地方+1),
跑到y的结束节点时,对于每个对应的查询x,求出x的子树中有多少个点就行了。
View Code
先把fail边反向建出fail树来。。
第x个字符串在第y个字符串中出现了多少次。对于y的每个前缀,如果它结尾可以通过fail跳到x的结尾的话,那么就出现了x。。
也就是查询x的fail子树中,有多少个y的节点。
在trie上暴力跑,在树状数组上加入根到当前节点路径上的点(将对应dfn值所在的地方+1),
跑到y的结束节点时,对于每个对应的查询x,求出x的子树中有多少个点就行了。
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int maxn=100233; struct zs{int too,pre;}e[maxn],e1[maxn];int tot,last[maxn],tot1,last1[maxn]; int too[maxn],pre[maxn],id[maxn],la[maxn],tt; int L[maxn],R[maxn],ed[maxn],tim; int t[maxn]; int fail[maxn],ch[maxn][26],dl[maxn],fa[maxn]; int i,j,k,n,m,cnt,node; int ans[maxn]; char s[maxn]; int ra;char rx; inline int read(){ rx=getchar(),ra=0; while(rx<'0'||rx>'9')rx=getchar(); while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; } inline void insert(int a,int b){e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;} inline void getfail(){ int l=0,r=1,i,now,p;dl[1]=0; while(l<r){ now=dl[++l]; for(i=0;i<26;i++)if(ch[now][i]){ dl[++r]=ch[now][i]; for(p=fail[now];p&&!ch[p][i];p=fail[p]); fail[ch[now][i]]=!now?0:ch[p][i],insert(fail[ch[now][i]],ch[now][i]); } } } void dfs(int x){ L[x]=++tim; for(int i=last[x];i;i=e[i].pre)dfs(e[i].too); R[x]=tim; } inline void ins(int a,int b){too[++tt]=b,id[tt]=i,pre[tt]=la[a],la[a]=tt;} inline void insgg(int a,int b){e1[++tot1].too=b,e1[tot1].pre=last1[a],last1[a]=tot1;} inline void add(int x){while(x<=node)t[x]++,x+=x&-x;} inline void del(int x){while(x<=node)t[x]--,x+=x&-x;} inline int query(int l,int r){ int sm=0;l--; while(r)sm+=t[r],r-=r&-r; while(l)sm-=t[l],l-=l&-l;return sm; } void dfs2(int x){ int i,x1,y,j;//printf("in: %d\n",x); if(x)add(L[x]); for(i=last1[x];i;i=e1[i].pre) for(y=e1[i].too,j=la[y];j;j=pre[j]) x1=too[j],ans[id[j]]=query(L[ed[x1]],R[ed[x1]]); for(i=0;i<26;i++)if(ch[x][i])/*printf("%d-->%d\n",x,ch[x][i]),*/dfs2(ch[x][i]); // printf("out: %d\n",x); if(x)del(L[x]); } int main(){ scanf("%s",s+1),n=strlen(s+1); int now=0; for(i=1;i<=n;i++){ if(s[i]=='P')cnt++,ed[cnt]=now,insgg(now,cnt);else if(s[i]=='B')now=fa[now];else if(!ch[now][s[i]-'a'])ch[now][s[i]-'a']=++node,fa[node]=now,now=node; else now=ch[now][s[i]-'a']; }node++; getfail(); dfs(0); m=read(); for(i=1;i<=m;i++)ins(read(),read()); dfs2(0); for(i=1;i<=m;i++)printf("%d\n",ans[i]); }
View Code
相关文章推荐
- MyBatis学习总结(一)——MyBatis快速入门
- 使用C++视频播放器库libvlc
- Java细粒度锁实现的3种方式
- js 按值传递与按引用传递
- Shell until循环
- 使用C++视频播放器库libvlc
- 映射关系级别注解
- java Excel导入导出,基于XML的实现,easy-excel使用
- Android学习笔记(闪屏淡入渐变效果)
- malloc&free与new&delete
- Zookeeper
- 动态规划--01背包问题 C++实现
- JavaWeb学习总结(五十三)——Web应用中使用JavaMail发送邮件
- 彻底理解ThreadLocal
- linux 常用命令
- 周年庆李宁老师课程全场5折!满998还送精品图书一本!
- nil Nil NULL及NSNull 之间的区别
- JavaWeb学习总结(五十二)——使用JavaMail创建邮件和发送邮件
- java代码模拟http请求
- linux mysql rpm 安装