[NOI 2011][BZOJ 2434] 阿狸的打字机
AC自动机 + 树状数组
建成AC自动机后,设end[i]为第i个串的末尾在Trie树上的节点。
可以发现,对于一个询问(x,y),ans等于Trie树上root到end[y]这条链上fail指针指向end[x]的节点数,我们把这些点记为特殊点
因为Trie树上每个节点fail指针仅指向一个值,
因此可以将fail指针反转构建一棵树,以下称为fail树。
于此答案可以等价于在fail树上以end[x]为根的子树中存在的特殊点个数。
然而这样暴力做还是过不了。于是需要一些优化。
可以知道将一个树的节点按dfs序排列后,
树的任意一颗子树的节点在序列中都是连续的一段区间。
我们把特殊的点记为1,非特殊点记为0,
于是求某子树上的特殊点个数可以转化成求某区间的和,
于是就可以用树状数组来优化了。(线段树应该也可以吧,不过似乎会比较麻烦)。
代码:
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring> using namespace std; #define N ((1<<17)-1)
#define M ((1<<17)-1)
#define lowbit(x) ((x)&(-(x))) queue<int>q;
char s[N];
int end[N],n; struct ACA
{
int cnt;
int fa[N],son[N][],fail[N];
void get_trie()
{
cnt=;
int i,now=,v,p=;
for (i=;i<n;i++)
switch(s[i])
{
case 'P':{end[++p]=now;break;}
case 'B':{now=fa[now];break;}
default:
{
v=s[i]-'a';
if (!son[now][v])
{
son[now][v]=++cnt;
fa[cnt]=now;
}
now=son[now][v];
}
}
for (i=;i<;i++) son[][i]=;
}
void get_fail()
{
int i,j,x;
q.push();
while (!q.empty())
{
x=q.front(),q.pop();
for (i=;i<;i++)
if (son[x][i])
{
for (j=fail[x];j&&!son[j][i];j=fail[j]);
fail[son[x][i]]=son[j][i];
q.push(son[x][i]);
}
}
}
}aca; struct BIT
{
int arr[N],l[N],r[N];
int sum(int i)
{
int re=;
while (i)
{re+=arr[i];i-=lowbit(i);}
return re;
}
void add(int i,int k)
{
while (i<=aca.cnt)
{arr[i]+=k;i+=lowbit(i);}
}
}bit; struct Tree
{
vector<vector<int> >son;
void addedge(int u,int v)
{
son[u].push_back(v);
}
void build()
{
son.resize(aca.cnt+);
for (int i=;i<=aca.cnt;i++)
addedge(aca.fail[i],i);
}
void dfs_order(int x,int &k)
{
bit.l[x]=bit.r[x]=k++;
for (int i=;i<son[x].size();i++)
{
dfs_order(son[x][i],k);
bit.r[x]=max(bit.r[x],bit.r[son[x][i]]);
}
}
}tree; int x[M],ans[M],pre[N],now[N]; inline int val(int x)
{
return bit.sum(bit.r[x])-bit.sum(bit.l[x]-);
} void answer()
{
int m,i,j,y,v,p;
scanf("%d",&m);
memset(now,,sizeof(now));
for (i=;i<=m;i++)
{
scanf("%d%d",&x[i],&y);
x[i]=end[x[i]];
y=end[y];
pre[i]=now[y];
now[y]=i;
}
for (p=,i=;i<n;i++)
{
switch(s[i])
{
case 'P':
{
for (j=now[p];j;j=pre[j])
ans[j]=val(x[j]);
break;
}
case 'B':
{
bit.add(bit.l[p],-);
p=aca.fa[p];
break;
}
default:
{
v=s[i]-'a';
p=aca.son[p][v];
bit.add(bit.l[p],);
}
}
}
for (i=;i<=m;i++)
printf("%d\n",ans[i]);
} int main()
{
scanf("%s",s);
n=strlen(s);
aca.get_trie();
aca.get_fail();
tree.build();
int k=;
tree.dfs_order(,k);
answer();
}
[NOI 2011][BZOJ 2434] 阿狸的打字机的更多相关文章
- AC自动机:BZOJ 2434 阿狸的打字机
2434: [Noi2011]阿狸的打字机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1834 Solved: 1053[Submit][Sta ...
- bzoj 2434 阿狸的打字机 - Aho-Corasick自动机 - 树状数组
题目传送门 传送站I 传送站II 题目大意 阿狸有一个打字机,它有3种键: 向缓冲区追加小写字母 P:打印当前缓冲区(缓冲区不变) B:删除缓冲区中最后一个字符 然后多次询问第$x$个被打印出来的串在 ...
- BZOJ 2434 阿狸的打字机(fail树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2434 题意:阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28 ...
- BZOJ 2434 阿狸的打字机
http://www.lydsy.com/JudgeOnline/problem.php?id=2434 思路:建立fail树,并找出dfs序,那剩下要做的就是每次找到一个串的位置,然后询问它的区间里 ...
- bzoj 2434: 阿狸的打字机 fail树+离线树状数组
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2434 题解: 首先我们可以发现这个打字的过程本身就是在Trie上滚来滚去的过程 所以我们 ...
- bzoj 2434 阿狸的打字机 fail树的性质
如果a串是另b串的后缀,那么在trie图上沿着b的fail指针走一定可以走到a串. 而a串在b串里出现多少次就是它是多少个前缀的后缀. 所以把fail边反向建树维护个dfs序就行了. 并不是很难... ...
- BZOJ 2434 阿狸的打字机 | AC自动机
题目戳这里 AC自动机上有神奇的东西叫做fail指针--所有fail指针连起来恰好构成一棵以1为根的树! 而这道题问x在y中出现过多少次,就是问Trie树上根到y的结束节点的路径上有多少节点能通过跳f ...
- BZOJ 2434 阿狸的打字机(ac自动机+dfs序+树状数组)
题意 给你一些串,还有一些询问 问你第x个串在第y个串中出现了多少次 思路 对这些串建ac自动机 根据fail树的性质:若x节点是trie中root到t任意一个节点的fail树的祖先,那么x一定是y的 ...
- 【BZOJ】【2434】【NOI2011】阿狸的打字机
AC自动机+DFS序+BIT 好题啊……orz PoPoQQQ 大爷 一道相似的题目:[BZOJ][3172][TJOI2013]单词 那道题也是在fail树上数有多少个点,只不过这题是在x的fail ...
随机推荐
- cnn 卷积神经网络 人脸识别
卷积网络博大精深,不同的网络模型,跑出来的结果是不一样,在不知道使用什么网络的情况下跑自己的数据集时,我建议最好去参考基于cnn的手写数字识别网络构建,在其基础上进行改进,对于一般测试数据集有很大的帮 ...
- Part2-HttpClient官方教程-Chapter7-高级主题(Advanced topics) (HTTP Caching)
原文链接 7.1 自定义客户端连接 在某些情况下,为了能够处理非标准的.不兼容的行为,可能需要自定义HTTP消息通过网络传输的方式,而不是使用HTTP参数.例如,对于web爬虫,可能有必要迫使Http ...
- ubuntu下调整cpu频率
环境:ubuntu15.10 查看内核支持的cpu策略 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors 比如我 ...
- js 实时显示字数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- python自动开发之第二十五天
一.组合搜索 参考: http://www.cnblogs.com/ccorz/p/5985205.html 二.JSONP 1.在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,但 ...
- 关于shutdown和close
示例代码: void str_cli(FILE *fp, int sockfd) { pid_t pid; char sendline[MAXLINE], recvline[MAXLINE]; ) { ...
- Linux-进程间通信(五): 网络套接字
不想说话,坑太深:持续学习网络编程中...
- 安全测试===sqlmap(贰)转载
十二.列举数据 这些参数用于列举出数据库管理系统信息.数据结构和数据内容. 1.一键列举全部数据 参数:--all 使用这一个参数就能列举所有可访问的数据.但不推荐使用,因为这会发送大量请求,把有用和 ...
- C基础 内存统一入口
引言 - malloc 引述 C标准中堆上内存入口就只有 malloc, calloc, realloc . 内存回收口是 free. 常见的一种写法是 struct person * per = ...
- java的集合类面试题
转自:https://yq.aliyun.com/articles/78788?spm=5176.8252056.759076.3.uFYrmt java.util包中包含了一系列重要的集合类,而对于 ...