BZOJ 2434 [Noi2011] 阿狸的打字机 Fail树
来源:互联网 发布:海通证券行情软件 编辑:程序博客网 时间:2024/05/19 00:49
2017.3.17补…
题目大意:造一台打字机(滑稽),要求支持:1.在末尾添加一个字符 2.删除结尾字符 3.打印当前字符串 4.回答打印出的第x个字符串在第y个字符串中出现了几次。
询问一个字符串在另一个字符串中的出现次数可以想到利用AC自动机中构造出的Fail树的性质(类似BZOJ3172)。要如何回答询问呢?
查询x在y中出现了几次,就是查询Fail树上x的子树中有多少个结点属于y.
这样的话,维护一个dfs序的树状数组(因为想求子树和,且子树在dfs序中是连续的),而对于一个单词,将他的所有节点插入到树状数组后就可以处理所有与其有关的询问。把所有询问建成一个邻接表,遇到P就处理所有有关这个字符串的询问,最后一起输出即可。
#include <cstdio>#include <cstring>#include <queue>#include <vector>#define pb push_back#define N 100005using namespace std;struct Edge { int u,v,nxt,ans;}query[N];int fir[N],st[N],ed[N];struct Node { Node *ch[26],*fail,*pa; int val,pos; vector<Node*> to; Node():val(0),fail(NULL),pa(NULL),pos(0) { to.clear(); memset(ch,0,sizeof ch); }}*root=new Node();int len,tot;char s[N];void Insert() { Node* o=root; for(int i=0;i<len;i++) { if(s[i]=='P') o->val=++tot; else if(s[i]=='B') o=o->pa; else { int z=s[i]-'a'; if(!o->ch[z]) o->ch[z]=new Node(), o->ch[z]->pa=o; o=o->ch[z]; } } return ;}void getFail() { queue<Node*> q; Node* o=root; for(int i=0;i<26;i++) if(o->ch[i]) { q.push(o->ch[i]); o->ch[i]->fail=o; o->to.pb(o->ch[i]); } else o->ch[i]=o; while(!q.empty()) { o=q.front(); q.pop(); for(int i=0;i<26;i++) if(o->ch[i]) { q.push(o->ch[i]); o->ch[i]->fail=o->fail->ch[i]; o->fail->ch[i]->to.pb(o->ch[i]); } else o->ch[i]=o->fail->ch[i]; } return ;}int T;namespace BIT { int c[N]; inline int lowbit(int x) {return x&-x;} void add(int x,int y) { for(int i=x;i<=T;i+=lowbit(i)) c[i]+=y; return ; } int sum(int x) { int tmp=0; for(int i=x;i;i-=lowbit(i)) tmp+=c[i]; return tmp; }}///build FailTreevoid dfs(Node* o) { o->pos=++T; if(o->val) st[o->val]=T; for(int i=0;i<o->to.size();i++) dfs(o->to[i]); if(o->val) ed[o->val]=T; return ;}void solve() { using namespace BIT; Node* o=root; for(int i=0;i<len;i++) { if(s[i]=='B') add(o->pos,-1), o=o->pa; else if(s[i]=='P') for(int j=fir[o->val];j;j=query[j].nxt) query[j].ans=sum(ed[query[j].v])-sum(st[query[j].v]-1); else { int z=s[i]-'a'; o=o->ch[z]; add(o->pos,1); } } return ;}int main() { scanf("%s",s); len=strlen(s); Insert(); getFail(); dfs(root); int n; scanf("%d",&n); for(int i=1;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); query[i].u=y; query[i].v=x; query[i].nxt=fir[y]; fir[y]=i; } solve(); for(int i=1;i<=n;i++) printf("%d\n",query[i].ans); return 0;}
1 0
- BZOJ 2434 [Noi2011] 阿狸的打字机 Fail树
- BZOJ 2434([Noi2011]阿狸的打字机-AC自动机-Fail树)
- BZOJ 2434 NOI2011 阿狸的打字机 fail树+树状数组
- [AC自动机 fail树 树状数组] BZOJ 2434 [NOI2011] 阿狸的打字机
- BZOJ 2434: [Noi2011]阿狸的打字机(fail树+树状数组)
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机 fail树
- bzoj 2434 [Noi2011]阿狸的打字机(AC自动机+fail树+dfs序+树状数组)
- bzoj-2434: [Noi2011]阿狸的打字机
- bzoj 2434: [Noi2011]阿狸的打字机
- BZOJ 2434 [Noi2011]阿狸的打字机
- BZOJ 2434 [Noi2011]阿狸的打字机
- bzoj 2434 [Noi2011]阿狸的打字机
- bzoj 2434: [Noi2011]阿狸的打字机
- BZOJ 2434 [Noi2011]阿狸的打字机
- bzoj 2434: [Noi2011]阿狸的打字机
- bzoj 2434: [Noi2011]阿狸的打字机
- 【BZOJ】【P2434】【Noi2011】【阿狸的打字机】【题解】【fail树+dfs序+树状数组】
- Charts.js 图例添加点击事件
- ubuntu配置jdk环境变量
- DDR原理
- 文章标题
- Android内存泄漏的简单检查与分析方法 ---待完善
- BZOJ 2434 [Noi2011] 阿狸的打字机 Fail树
- 微信小程序之商城分类详情
- 0117考试总结
- 第60篇 释放摄像头研究及安卓和IOS共用一套代码(二)
- leetcode--66. Plus One
- 股票入门基础知识29:如何运用日本蜡烛图进行技术分析
- UIA(0)-引子
- 关于Java动态编程的简单总结
- 随笔20170117