正解:AC自动机+树状数组/线段树

解题报告:

传送门!

这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有70pts

然后思考一下,正解怎么做呢QAQ

回到AC自动机中关于fail指针的定义上来,因为fail指针指向的是最长后缀,这意味着,假如a指向b,那么a字符串中一定包含有root到b这一段字符串

于是假如我们要统计的字符串x,就只需要统计有多少个fail指针直接或间接指向x的ed那个点就是as辣

那不就是,建一棵fail树,求对于节点x的子树中有多少个节点是属于y的嘛

于是就考虑先dfs一下求出dfs序,然后这题就转化了鸭,就变成了这样:

有一个序列,支持向尾部加数和减数操作,每次只能操作一个数,然后还有一个询问操作,就是问[x,y]这个区间里有多少个数

那不就是线段树走一波就完事儿了嘛!

但是再仔细一想

这个询问操作其实还有一个性质

它的y一定是当前序列的最后一个数

那树状数组不就完事了嘛(主要树状数组比较好打+时空复杂度什么的比较好看,,,

然后就over辣!

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define ll int
  4. #define il inline
  5. #define rg register
  6. #define lowbit(x) (x&(-x))
  7. #define rp(i,x,y) for(rg ll i=x;i<=y;++i)
  8.  
  9. const ll L=+,N=+;
  10. ll cnt,tot,num,m,ed[L],dfn[L],low[L],edcnt,strlenth,tree[N],head[N],wdcnt,ans[N];
  11. string str;
  12. struct tre{ll to[],fil,fa;tre(){to[]=to[]=;fil=;}}tr[L];
  13. struct qust{ll x,y,id;}as[N];
  14. struct ed{ll to,nxt;}edge[L];
  15.  
  16. il ll read()
  17. {
  18. rg char ch=getchar();rg ll x=;rg bool y=;
  19. while(ch!='-' && (ch>'' || ch<''))ch=getchar();
  20. if(ch=='-')ch=getchar(),y=;
  21. while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=getchar();
  22. return y?x:-x;
  23. }
  24. il void bd()
  25. {
  26. cin>>str;strlenth=str.length();ll nw=;
  27. rp(i,,strlenth)
  28. {
  29. if(str[i]>='a' && str[i]<='z'){if(!tr[nw].to[str[i]-'a'])tr[nw].to[str[i]-'a']=++cnt,tr[cnt].fa=nw;nw=tr[nw].to[str[i]-'a'];}
  30. if(str[i]=='B')nw=tr[nw].fa;
  31. if(str[i]=='P')ed[++tot]=nw;
  32. }
  33. }
  34. il void ad(ll x,ll y){edge[++edcnt].to=y;edge[edcnt].nxt=head[x];head[x]=edcnt;}
  35. il void fl()
  36. {
  37. queue<ll> Q;rp(i,,)if(tr[].to[i])Q.push(tr[].to[i]),ad(,tr[].to[i]);
  38. while(!Q.empty())
  39. {
  40. ll nw=Q.front();Q.pop();
  41. rp(i,,){if(tr[nw].to[i])tr[tr[nw].to[i]].fil=tr[tr[nw].fil].to[i],Q.push(tr[nw].to[i]),ad(tr[tr[nw].to[i]].fil,tr[nw].to[i]);else tr[nw].to[i]=tr[tr[nw].fil].to[i];}
  42. }
  43. }
  44. il void dfs(ll x){/*printf("x=%d\n",x);*/dfn[x]=++num;for(rg ll i=head[x];i;i=edge[i].nxt)dfs(edge[i].to);low[x]=num;}
  45. il bool cmp(qust gd,qust gs){return gd.y<gs.y;}
  46. il void updat(ll x,ll y){while(x<N)tree[x]+=y,x+=lowbit(x);}
  47. il ll query(ll x){ll as=;while(x)as+=tree[x],x-=lowbit(x);return as;}
  48. il void solv()
  49. {
  50. ll nw=,nwnw=;
  51. rp(i,,strlenth-)
  52. {
  53. // printf("QAQ? : ");cout<<str[i]<<endl;
  54. if(str[i]>='a' && str[i]<='z')nwnw=tr[nwnw].to[str[i]-'a'],updat(dfn[nwnw],);
  55. if(str[i]=='B')updat(dfn[nwnw],-),nwnw=tr[nwnw].fa;
  56. if(str[i]=='P')
  57. {
  58. ++wdcnt;
  59. // printf("cnt=%d\n",wdcnt);
  60. while(as[nw].y==wdcnt && nw<=m)
  61. {
  62. // printf("nw=%d\n",nw);
  63. ll tmp=ed[as[nw].x];
  64. ans[as[nw].id]=query(low[tmp])-query(dfn[tmp]-),++nw;
  65. }
  66. // if(nw>m)return;
  67. }
  68. }
  69. return;
  70. }
  71.  
  72. int main()
  73. {
  74. bd();fl();dfs();m=read();rp(i,,m){as[i].x=read(),as[i].y=read(),as[i].id=i;/*if(as[i].y==1)printf("id=%d\n",i);*/}sort(as+,as++m,cmp);solv();
  75. // rp(i,0,cnt)printf("dfn=%d low=%d\n",dfn[i],low[i]);
  76. rp(i,,m)printf("%d\n",ans[i]);
  77. return ;
  78. }
  79. /*
  80. ,,,我佛了我发现这题太复杂了
  81. 我来理下思路
  82. 首先确定一下各个变量的作用,,,
  83. const ll L=100000+500,N=100000+100;
  84. 常数变量,L是字母个数,N是询问个数
  85. ll cnt,tot,num,m,ed[L],dfn[L],low[L],edcnt,strlenth,tree[N],head[N],wdcnt,ans[N];
  86. cnt,建AC自动机的时候用
  87. tot,存ed的时候用
  88. num,存dfn序的时候用
  89. ed[],存询问的节点编号
  90. dfn[],存dfs序,即题解中[x,y]的x
  91. low[],同上,即y
  92. edcnt,连边的时候用
  93. strlenth,存str的长度
  94. tree[],树状数组
  95. head[],链式前向星一部分
  96. wdcnt,存做到哪个单词了
  97. ans[],存答案
  98. string str;
  99. 读入的那个字符串
  100. struct tre{ll to[30],fil,fa;tre(){to[0]=to[1]=0;fil=0;}}tr[L];
  101. trie树 to和fil不说,fa是为了Back操作
  102. struct qust{ll x,y,id,ass;}as[N];
  103. 存询问,方便排序和再排
  104. struct ed{ll to,nxt;}edge[L];
  105. 存边
  106. 然后明确一下工作
  107. bd();
  108. 读入字符串,建trie树:main函数中操作
  109. ad();
  110. 连边,fail指向节点:fl中操作
  111. fl();
  112. 建fail指针:main函数中操作
  113. dfs();
  114. 记dfs序:main函数中操作
  115. cmp();
  116. 排序,保证疑问y递增:main函数sort中操作
  117. updat();
  118. 树状数组+-操作:solv中操作
  119. query();
  120. 树状数组求值操作:solv中操作
  121. solv();
  122. 求ans:main函数中操作
  123. 欧克克我jio得现在思路海星了大概是细节有点儿问题下午搞QAQ
  124. */

总算过辣呜呜呜

洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树的更多相关文章

  1. 洛谷P2414 阿狸的打字机【AC自动机】【fail树】【dfs序】【树状数组】

    居然真的遇上了这种蔡队题.瑟瑟发抖. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿 ...

  2. [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?

    其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...

  3. 【洛谷4396/BZOJ3236】[AHOI2013]作业(莫队+分块/树状数组/线段树)

    题目: 洛谷4396 BZOJ3236(权限) 这题似乎BZOJ上数据强一些? 分析: 这题真的是--一言难尽 发现题面里没说权值的范围,怕出锅就写了离散化.后来经过面向数据编程(以及膜神犇代码)知道 ...

  4. 洛谷P2414 阿狸的打字机

    题意:以trie的形式给出n个字符串,每次询问第x个字符串在第y个字符串中出现了几次. 解:总串长是n2级别的,所以不能用什么后缀自动机... [update]可以建triesam但是不知道trie上 ...

  5. 洛谷P2880 [USACO07JAN] Balanced Lineup G(树状数组/线段树)

    维护区间最值的模板题. 1.树状数组 1 #include<bits/stdc++.h> 2 //树状数组做法 3 using namespace std; 4 const int N=5 ...

  6. 【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  7. 【BZOJ2434】阿狸的打字机(AC自动机,树状数组)

    [BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...

  8. BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)

    [NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...

  9. BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2434 给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字 ...

随机推荐

  1. Memcache未授权访问漏洞

    Memcached 分布式缓存系统,默认的 11211 端口不需要密码即可访问,黑客直接访问即可获取数据库中所有信息,造成严重的信息泄露. 0X00 Memcache安装 1. 下载Mencache的 ...

  2. Nginx 访问日志

    配置访问日志: [root@localhost ~]$ cat /usr/local/nginx/conf/nginx.conf http { log_format main '$remote_add ...

  3. 《转载》脚本实现从客户端服务端HTTP请求快速分析

    本文转载自https://www.imooc.com/article/14107 首先我想介绍下,分享这个脚本的用处: 当客户告知我们,一个页面http://www.xxx.com 有问题时,作为PE ...

  4. apache使某目录下的文件能够列表显示出来

    想要使web目录下,某目录下的文件列表显示而不是显示"You don't have permission to access / on this server" 需要在httpd. ...

  5. php pear包打包方法

    一)首先下载工具onion 浏览器打开,服务器上wget测试无法正常下载 地址:https://raw.github.com/c9s/Onion/master/onion 二)在临时目录下,建立相关目 ...

  6. 【技术分享会】 @第五期 angularjs

    前言 AngularJS 最初由Misko Hevery 和Adam Abrons于2009年开发,后来成为了Google公司的项目.AngularJS弥补了HTML在构建应用方面的不足,其通过使用标 ...

  7. 日记整理---->2016-11-21

    2016-11-21简单的总结一下学到的知识点.作为一个目标而存在的东西,总是那么美丽而优雅. 一.PE中事务的编写 getTransactionTemplate().execute(new Tran ...

  8. 关于SQL优化(转载,格式有调整)

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  9. MFC onpaint() ondraw()

    OnPaint是WM_PAINT消息的消息处理函数,在OnPaint中调用OnDraw,一般来说,用户自己的绘图代码应放在OnDraw中. OnPaint()是CWnd的类成员,负责响应WM_PAIN ...

  10. Nginx写IO占用高故障处理

    文章来源:<https://www.centos.bz/2015/04/handle-nginx-write-io-problem/> 故障现象 突然收到一台服务器负载过高告警,紧接着网站 ...