【BZOJ2434-[Noi2011]】阿狸的打字机(AC自动机(fail树)+离线+树状数组)
Description
阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。
经阿狸研究发现,这个打字机是这样工作的:
l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。
l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。
l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。
例如,阿狸输入aPaPBbP,纸上被打印的字符如下:
a
aa
ab
我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。
阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?
Input
输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。
第二行包含一个整数m,表示询问个数。
接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。
Output
输出m行,其中第i行包含一个整数,表示第i个询问的答案。
Sample Input
aPaPBbP3
1 2
1 3
2 3
Sample Output
21
0
HINT
1<=N<=10^5
1<=M<=10^5输入总长<=10^5
【分析】
- 这道题是用AC自动机里的fail指针连成的树做的。
- 用到fail树。
- 首先有一个朴素算法就是找到第y个单词在trie树上的路径然后沿着每一个点的fail指针走,如果找到x就加1(想想fail指针建立的过程)。
- 由此可以运用逆向思维,以x为根的子树沿着fail指针倒着走能找到多少个y路径上的点就说明x在y上出现过几次。每次都dfs找一遍,用树状数组维护,这样可以得到70分。
- 同时这是一个离线算法,一遍dfs,遇到一个结束标记,就做一下这个串的询问,插一个点在树状数组+1,离开这个点时-1。
- 对于树上每个点只插入一次,时间复杂度就得到了保证。
有一个很详细的题解:http://blog.csdn.net/huzecong/article/details/7769988
代码如下:(丑)
- #include<cstdio>
- #include<cstdlib>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- using namespace std;
- #define Maxn 100100
- #define Maxl 100010
- char s[Maxl];
- int p[Maxn];
- struct hp
- {
- int x,y,next,id,ans;
- }qy[Maxn];int al;
- struct node
- {
- int son[],cnt,fail;
- int num,rt,fa,st;
- }t[Maxn];int tot;
- int first[Maxn],c[Maxn];
- bool cmp(hp x,hp y) {return p[x.y]<p[y.y];}
- bool cmp2(hp x,hp y) {return x.id<y.id;}
- void ins(int x,int y)
- {
- qy[++al].x=x;qy[al].y=y;
- qy[al].next=first[x];first[x]=al;
- }
- void upd(int x,int f)
- {
- t[x].cnt=;t[x].fa=f;t[x].st=;
- memset(t[x].son,,sizeof(t[x].son));
- }
- void read_trie()
- {
- scanf("%s",s+);
- int len=strlen(s+);
- memset(p,,sizeof(p));
- int now=;int ql=;tot=;
- for(int j=;j<=len;j++)
- {
- if(s[j]>='a'&&s[j]<='z')
- {
- int ind=s[j]-'a'+;
- if(!t[now].son[ind])
- t[now].son[ind]=++tot,upd(tot,now);
- now=t[now].son[ind];
- if(j==len) t[now].cnt++;
- }
- else if(s[j]=='B') now=t[now].fa;
- else p[++ql]=now;
- }
- }
- queue<int > q;
- void build_AC()
- {
- int i,j,x,y;
- while(!q.empty()) q.pop();
- q.push();
- while(!q.empty())
- {
- x=q.front();
- y=t[x].fail;
- for(j=;j<=;j++)
- {
- if(t[x].son[j])
- {
- q.push(t[x].son[j]);
- t[t[x].son[j]].fail=x?t[y].son[j]:x;
- ins(t[t[x].son[j]].fail,t[x].son[j]);
- }
- else t[x].son[j]=t[y].son[j];
- }
- q.pop();
- }
- }
- void dfs(int x)
- {
- t[x].num=++al;t[x].rt=t[x].num;
- for(int i=first[x];i;i=qy[i].next)
- dfs(qy[i].y),t[x].rt=t[qy[i].y].rt;
- }
- void add(int x,int y)
- {
- for(int i=x;i<=tot+;i+=i&(-i))
- c[i]+=y;
- }
- int getsum(int x)
- {
- int ans=;
- for(int i=x;i>=;i-=i&(-i))
- ans+=c[i];
- return ans;
- }
- void dfs2(int x)
- {
- add(t[x].num,);
- if(t[x].st!=)
- {
- for(int i=t[x].st;;i++)
- {
- if(p[qy[i].y]!=x) break;
- qy[i].ans=getsum(t[p[qy[i].x]].rt)-getsum(t[p[qy[i].x]].num-);
- }
- }
- for(int i=;i<=;i++) if(t[x].son[i]&&t[t[x].son[i]].fa==x)
- {
- dfs2(t[x].son[i]);
- }
- add(t[x].num,-);
- }
- void init()
- {
- memset(first,,sizeof(first));
- al=;
- read_trie();
- build_AC();al=;
- dfs();
- int m;
- scanf("%d",&m);
- for(int i=;i<=m;i++) {scanf("%d%d",&qy[i].x,&qy[i].y);qy[i].id=i;}
- sort(qy+,qy++m,cmp);
- qy[].y=;
- for(int i=;i<=m;i++)
- if(p[qy[i].y]!=p[qy[i-].y]) t[p[qy[i].y]].st=i;
- else t[p[qy[i].y]].st=t[p[qy[i-].y]].st;
- memset(c,,sizeof(c));
- dfs2();
- sort(qy+,qy++m,cmp2);
- for(int i=;i<=m;i++) printf("%d\n",qy[i].ans);
- }
- int main()
- {
- init();
- return ;
- }
[BZOJ2434]
2016-06-16 16:55:20
【BZOJ2434-[Noi2011]】阿狸的打字机(AC自动机(fail树)+离线+树状数组)的更多相关文章
- BZOJ 2434: [Noi2011]阿狸的打字机 [AC自动机 Fail树 树状数组 DFS序]
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2545 Solved: 1419[Submit][Sta ...
- 【BZOJ-2434】阿狸的打字机 AC自动机 + Fail树 + DFS序 + 树状数组
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 2022 Solved: 1158[Submit][Sta ...
- BZOJ2434: [Noi2011]阿狸的打字机(AC自动机 树状数组)
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4140 Solved: 2276[Submit][Status][Discuss] Descript ...
- BZOJ2434[Noi2011]阿狸的打字机——AC自动机+dfs序+树状数组
题目描述 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小 ...
- BZOJ2434:[NOI2011]阿狸的打字机(AC自动机,线段树)
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- [BZOJ2434][Noi2011]阿狸的打字机 AC自动机+树状数组+离线
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题目中这种多个串匹配的问题,一下子就想到了AC自动机.然后发现如果要建立AC自动机, ...
- BZOJ 2434: [Noi2011]阿狸的打字机 AC自动机+fail树+线段树
Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的 ...
- 【BZOJ2434】[NOI2011]阿狸的打字机 AC自动机+DFS序+树状数组
[BZOJ2434][NOI2011]阿狸的打字机 Description 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- [NOI2011]阿狸的打字机 --- AC自动机 + 树状数组
[NOI2011] 阿狸的打字机 题目描述: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现, ...
随机推荐
- datebox清除按钮,datebox加上清除按钮,easyui datebox加上清除按钮
datebox加上清除按钮,easyui datebox加上清除按钮 >>>>>>>>>>>>>>>>& ...
- Linux安装QQ 2017
网上有很多wineQQ,是基于2012或者2013做的,然而当安装好后登录他会提示版本过来,我在优麒麟的应用商店里找到了一个基于国际版QQ的Wine版本,这里说下安装过程. 先上两张成果图: 下载地址 ...
- SqlServer循环读取配置
USE [DB_JP_BaseInfo00] GO /****** Object: StoredProcedure [dbo].[sp_wx_getAppointmentInfo_Str] Scrip ...
- 程序员带你十天快速入门Python,玩转电脑软件开发(四)
本系列文章立志于从一个已经习得一门编程语言的基础之上,全面介绍Python的相关开发过程和相关经验总结.本篇文章主要是基于上一篇的程序员带你十天快速入门Python,玩转电脑软件开发(三)的基础之上, ...
- ASCII 对应表 CHR()
chr(9) tab空格 chr(10) 换行 chr(13) 回车 chr(13)&chr(10) 回车换行 chr(32) 空格符 ...
- js--小结⑤
js中的for循环,while循环,do...while循环和C语言的一模一样 有几个问题要提醒一下的是 1. null是对象,即object undefined是undefined d ...
- Java-Android 之应用停止错误
在Android在手机上运行的时候: 经常会出现应用程序停止: 一: 因为触发的方法里面没有传值View 对象,方法报错
- Android基础问题汇总
一.android:gravity 和android:layout_gravity的区别: android;gravity是自己的内容相对于自己的控件的位置,而android:layout_gravi ...
- javascript类继承系列一
js中没有提供类(class,抽象类,接口等高级的抽象),可以用new,但new的function的对象,构造器 但在js中可以通过function来模拟类的一些特性function fun_name ...
- dense_rank()+hash提示改写优化SQL
数据库环境:SQL SERVER 2005 今天看到一条SQL,返回10条数据,执行了50多S.刚好有空,就对它进行了优化,优化后1S出结果. 先看下原始SQL SELECT t1.line_no , ...