P2414 [NOI2011]阿狸的打字机

题目背景

阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。

题目描述

打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。经阿狸研究发现,这个打字机是这样工作的:

·输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

·按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

·按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

a aa ab 我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

输入输出格式

输入格式:

输入的第一行包含一个字符串,按阿狸的输入顺序给出所有阿狸输入的字符。

第二行包含一个整数m,表示询问个数。

接下来m行描述所有由小键盘输入的询问。其中第i行包含两个整数x, y,表示第i个询问为(x, y)。

输出格式:

输出m行,其中第i行包含一个整数,表示第i个询问的答案。

说明

数据范围:

对于100%的数据,n<=100000,m<=100000,第一行总长度<=100000。


这题一下子让我爱上了AC自动机...

先考虑把自动机建出来看看如何暴力。

每次询问时我们暴力跳\(y\)串每个字符的\(fail\)数组,中间遇到\(x\)串的末尾时答案加1

考虑优化这个过程

把\(fail\)数组构成的边反向建图,得到一颗树

这时候询问可以变成\(x\)串末尾那个点的子树中有多少点属于\(y\)

我们可以先把\(fail\)树遍历一遍,给点编上编号\(dfn\),这样子树的编号就是连续的了

我们\(dfs\)原\(tire\)树,遍历到一个点时把它的\(dfn[x]+1\),从这个点出去时就把\(dfn[x]-1\)

每次到达一个串末尾时,我们处理它成为\(y\)的询问,查询每个\(x\)的子树,可以用树状数组维护

可以发现,每次只有一条链上的值被增加过

复杂度:\(O(nlogn)\)


Code:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N=1e5+10;
int Next[N<<1],to[N<<1],head[N],cnt;
void add(int u,int v)
{
to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
}
int ch[N][26],fail[N],f[N],num[N],las[N],is[N][26],tot,n;
char s[N];
void init()
{
scanf("%s",s+1);
for(int now=0,i=1;i<=strlen(s+1);i++)
{
if(s[i]=='P') las[++n]=now,num[now]=n;
else if(s[i]=='B') now=f[now];
else
{
if(!ch[now][s[i]-'a']) ch[now][s[i]-'a']=++tot,f[tot]=now;
now=ch[now][s[i]-'a'];
}
}
}
int q[N],l,r;
void build()
{
l=1,r=0;
int now=0;
for(int i=0;i<26;i++)
if(ch[now][i])
is[now][i]=1,add(0,ch[now][i]),q[++r]=ch[now][i];
while(l<=r)
{
now=q[l++];
for(int i=0;i<26;i++)
{
int v=ch[now][i];
if(v) is[now][i]=1,fail[v]=ch[fail[now]][i],add(ch[fail[now]][i],v),q[++r]=v;
else ch[now][i]=ch[fail[now]][i];
}
}
}
int dfn[N],siz[N],dfs_clock,ans[N],sum[N];
void dfs0(int now)
{
dfn[now]=++dfs_clock;
siz[now]=1;
for(int i=head[now];i;i=Next[i])
dfs0(to[i]),siz[now]+=siz[to[i]];
}
struct node
{
int id,to;
};
vector <node> ask[N];
int query(int x)
{
int su=0;while(x) su+=sum[x],x-=x&-x;
return su;
}
void modify(int x,int d)
{
while(x<=dfs_clock) sum[x]+=d,x+=x&-x;
}
void dfs(int now)
{
modify(dfn[now],1);
if(num[now])
{
int x=num[now];
for(int i=0;i<ask[x].size();i++)
{
int id=ask[x][i].id,to=las[ask[x][i].to];
ans[id]=query(dfn[to]+siz[to]-1)-query(dfn[to]-1);
}
}
for(int i=0;i<26;i++)
{
int v=ch[now][i];
if(is[now][i]) dfs(v);
}
modify(dfn[now],-1);
}
void work()
{
build();
int m;
scanf("%d",&m);
for(int x,y,i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
node tt={i,x};
ask[y].push_back(tt);
}
dfs0(0);
dfs(0);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
}
int main()
{
init();
work();
return 0;
}

PS:我犯了个很傻的错误调了快一个小时

    while(l<=r)
{
now=q[l++];
for(int i=0;i<26;i++)
{
int v=ch[now][i];
if(v) is[now][i]=1,fail[v]=ch[fail[now]][i],add(ch[fail[now]][i],v),q[++r]=v;
else v=ch[fail[now]][i];
}
}
    while(l<=r)
{
now=q[l++];
for(int i=0;i<26;i++)
{
int v=ch[now][i];
if(v) is[now][i]=1,fail[v]=ch[fail[now]][i],add(ch[fail[now]][i],v),q[++r]=v;
else ch[now][i]=ch[fail[now]][i];
}
}

2018.8.29

最新文章

  1. 【填坑向】bzoj2038小Z的袜子 莫队
  2. MVC5 + EF6 简单示例
  3. Hello Point——WebGL
  4. INF文件的安装/卸载命令
  5. Asp.net Mvc 身份验证、异常处理、权限验证(拦截器)实现代码
  6. Objective-C:Foundation框架-常用类-NSMutableDictionary
  7. (easy)LeetCode 202.Happy Number
  8. Table 样式设置
  9. poj 2185 (KMP)
  10. bootstrap table 行号 显示行号 添加行号 bootstrap-table 行号
  11. 使用pymysql连接MySql数据库
  12. CSS3图片轮播效果
  13. 图片上传预览 支持html5的浏览器
  14. Single Number leetcode
  15. cannot import name &#39;ChineseAnalyzer&#39;
  16. SCNN车道线检测--(SCNN)Spatial As Deep: Spatial CNN for Traffic Scene Understanding(论文解读)
  17. DB Query Analyzer 5.03 is distributed, EXCEL table name will be enclosed in square bracket
  18. 用js制作数码时钟
  19. windows环境下mysql密码重置
  20. A.01.09—模块的输出—PWM低端输出

热门文章

  1. java服务端项目开发规范
  2. 程序设计的SOLID原则
  3. C语言实例解析精粹学习笔记——31
  4. C语言数据结构(二)
  5. 深度学习:激活函数的比较和优缺点,sigmoid,tanh,relu
  6. MYSQL--事务处理(转)
  7. github简单使用教程(转)
  8. 步骤2:JMeter 分布式测试(性能测试大并发、远程启动解决方案)
  9. 关于python的闭包与装饰器的实验
  10. zabbix 通过key(键值)获取信息