洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树
正解: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辣!
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define il inline
#define rg register
#define lowbit(x) (x&(-x))
#define rp(i,x,y) for(rg ll i=x;i<=y;++i) const ll L=+,N=+;
ll cnt,tot,num,m,ed[L],dfn[L],low[L],edcnt,strlenth,tree[N],head[N],wdcnt,ans[N];
string str;
struct tre{ll to[],fil,fa;tre(){to[]=to[]=;fil=;}}tr[L];
struct qust{ll x,y,id;}as[N];
struct ed{ll to,nxt;}edge[L]; il ll read()
{
rg char ch=getchar();rg ll x=;rg bool y=;
while(ch!='-' && (ch>'' || ch<''))ch=getchar();
if(ch=='-')ch=getchar(),y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=getchar();
return y?x:-x;
}
il void bd()
{
cin>>str;strlenth=str.length();ll nw=;
rp(i,,strlenth)
{
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'];}
if(str[i]=='B')nw=tr[nw].fa;
if(str[i]=='P')ed[++tot]=nw;
}
}
il void ad(ll x,ll y){edge[++edcnt].to=y;edge[edcnt].nxt=head[x];head[x]=edcnt;}
il void fl()
{
queue<ll> Q;rp(i,,)if(tr[].to[i])Q.push(tr[].to[i]),ad(,tr[].to[i]);
while(!Q.empty())
{
ll nw=Q.front();Q.pop();
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];}
}
}
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;}
il bool cmp(qust gd,qust gs){return gd.y<gs.y;}
il void updat(ll x,ll y){while(x<N)tree[x]+=y,x+=lowbit(x);}
il ll query(ll x){ll as=;while(x)as+=tree[x],x-=lowbit(x);return as;}
il void solv()
{
ll nw=,nwnw=;
rp(i,,strlenth-)
{
// printf("QAQ? : ");cout<<str[i]<<endl;
if(str[i]>='a' && str[i]<='z')nwnw=tr[nwnw].to[str[i]-'a'],updat(dfn[nwnw],);
if(str[i]=='B')updat(dfn[nwnw],-),nwnw=tr[nwnw].fa;
if(str[i]=='P')
{
++wdcnt;
// printf("cnt=%d\n",wdcnt);
while(as[nw].y==wdcnt && nw<=m)
{
// printf("nw=%d\n",nw);
ll tmp=ed[as[nw].x];
ans[as[nw].id]=query(low[tmp])-query(dfn[tmp]-),++nw;
}
// if(nw>m)return;
}
}
return;
} int main()
{
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();
// rp(i,0,cnt)printf("dfn=%d low=%d\n",dfn[i],low[i]);
rp(i,,m)printf("%d\n",ans[i]);
return ;
}
/*
,,,我佛了我发现这题太复杂了
我来理下思路
首先确定一下各个变量的作用,,,
const ll L=100000+500,N=100000+100;
常数变量,L是字母个数,N是询问个数
ll cnt,tot,num,m,ed[L],dfn[L],low[L],edcnt,strlenth,tree[N],head[N],wdcnt,ans[N];
cnt,建AC自动机的时候用
tot,存ed的时候用
num,存dfn序的时候用
ed[],存询问的节点编号
dfn[],存dfs序,即题解中[x,y]的x
low[],同上,即y
edcnt,连边的时候用
strlenth,存str的长度
tree[],树状数组
head[],链式前向星一部分
wdcnt,存做到哪个单词了
ans[],存答案
string str;
读入的那个字符串
struct tre{ll to[30],fil,fa;tre(){to[0]=to[1]=0;fil=0;}}tr[L];
trie树 to和fil不说,fa是为了Back操作
struct qust{ll x,y,id,ass;}as[N];
存询问,方便排序和再排
struct ed{ll to,nxt;}edge[L];
存边
然后明确一下工作
bd();
读入字符串,建trie树:main函数中操作
ad();
连边,fail指向节点:fl中操作
fl();
建fail指针:main函数中操作
dfs();
记dfs序:main函数中操作
cmp();
排序,保证疑问y递增:main函数sort中操作
updat();
树状数组+-操作:solv中操作
query();
树状数组求值操作:solv中操作
solv();
求ans:main函数中操作
欧克克我jio得现在思路海星了大概是细节有点儿问题下午搞QAQ
*/
总算过辣呜呜呜
洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树的更多相关文章
- 洛谷P2414 阿狸的打字机【AC自动机】【fail树】【dfs序】【树状数组】
居然真的遇上了这种蔡队题.瑟瑟发抖. 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. 题目描述 打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿 ...
- [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?
其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...
- 【洛谷4396/BZOJ3236】[AHOI2013]作业(莫队+分块/树状数组/线段树)
题目: 洛谷4396 BZOJ3236(权限) 这题似乎BZOJ上数据强一些? 分析: 这题真的是--一言难尽 发现题面里没说权值的范围,怕出锅就写了离散化.后来经过面向数据编程(以及膜神犇代码)知道 ...
- 洛谷P2414 阿狸的打字机
题意:以trie的形式给出n个字符串,每次询问第x个字符串在第y个字符串中出现了几次. 解:总串长是n2级别的,所以不能用什么后缀自动机... [update]可以建triesam但是不知道trie上 ...
- 洛谷P2880 [USACO07JAN] Balanced Lineup G(树状数组/线段树)
维护区间最值的模板题. 1.树状数组 1 #include<bits/stdc++.h> 2 //树状数组做法 3 using namespace std; 4 const int N=5 ...
- 【BZOJ2434】【NOI2011】阿狸的打字机(AC自动机,树状数组)
[BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...
- 【BZOJ2434】阿狸的打字机(AC自动机,树状数组)
[BZOJ2434]阿狸的打字机(AC自动机,树状数组) 先写个暴力: 每次打印出字符串后,就插入到\(Trie\)树中 搞完后直接搭\(AC\)自动机 看一看匹配是怎么样的: 每次沿着\(AC\)自 ...
- BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)
[NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...
- BZOJ_2434_[NOI2011]_阿狸的打字机_(AC自动机+dfs序+树状数组)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=2434 给出\(n\)个字符串,\(m\)个询问,对于第\(i\)个询问,求第\(x_i\)个字 ...
随机推荐
- Qt打包部署程序自动查找依赖DLL工具windeployqt
qt编译好一个exe程序之后,部署到一台没有开发环境的机器上,需要一起拷贝其依赖的dll文件.这时需要一个windeployqt工具来帮忙,因为手动拷贝的话容易遗漏. https://blog.csd ...
- Jar命令
JAR包是Java中所特有一种压缩文档,其实大家就可以把它理解为.zip包;当然也是有区别的,JAR包中有一个META-INF\MANIFEST.MF文件,当你打成JAR包时,它会自动生成. 一.ja ...
- 在 Linux 使用 GCC 编译C语言共享库
对任何程序员来说库都是必不可少的.所谓的库是指已经编译好的供你使用的代码.它们常常提供一些通用功能,例如链表和二叉树可以用来保存任何数据,或者是一个特定的功能例如一个数据库服务器的接口,就像MySQL ...
- mac 常用的终端命令
OSX 的文件系统 OSX 采用的Unix文件系统,所有文件都挂在跟目录 / 下面,所以不在要有Windows 下的盘符概念. 你在桌面上看到的硬盘都挂在 /Volumes 下. 比如接上个叫做 US ...
- mybais 之parameterType ="list"
<!-- 根据货品编号获取商品价格和库存 --> <select id="getGoodsPriceAndStockByGoodsNo" resultMap=&q ...
- C语言中的正负数及其输出
在数学中,数字有正负之分.在C语言中也是一样,short.int.long 都可以带上正负号,例如: //负数 ; short a2 = -0x2dc9; //十六进制 //正数 ; ; //八进制 ...
- [原]如何为SqlServer2008数据库分配用户
前言: 当一个项目完成后,为了数据安全,总会对该项目的数据库分配一个用户,应该说总会创建一个用户来管理这个数据库,并且这个用户只能管理这个数据库.搞了好多次,每次都忘记怎么设置,所以写一篇博文记录一下 ...
- myisam与innodb索引比较
MyISAM支持全文索引(FULLTEXT).压缩索引,InnoDB不支持 InnoDB支持事务,MyISAM不支持 MyISAM顺序储存数据,索引叶子节点保存对应数据行地址,辅助索引很主键索引相差无 ...
- Struts2之命名空间与Action的三种创建方式
看到上面的标题,相信大家已经知道我们接下来要探讨的知识了,一共两点:1.package命名空间设置:2.三种Action的创建方式.下面我们开始本篇的内容: 首先我们聊一聊命名空间的知识,namesp ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十:PS/2模块④ — 普通鼠标
实验十:PS/2模块④ - 普通鼠标 学习PS/2键盘以后,接下来就要学习 PS/2 鼠标.PS/2鼠标相较PS/2键盘,驱动难度稍微高了一点点,因为FPGA(从机)不仅仅是从PS/2鼠标哪里读取数据 ...