HDU4787 GRE Words Revenge【AC自动机 分块】
HDU4787 GRE Words Revenge
题意:
\(N\)次操作,每次记录一个\(01\)串或者查询一个\(01\)串能匹配多少个记录的串,强制在线
题解:
在线的AC自动机,利用分块来降低复杂度,建两个AC自动机,一个大的一个小的,每次往小的里面加字符串,当小的自动机的大小大于一定值之后把小的自动机和大的自动机合并,然后清空小的自动机
每次询问把小的自动机和大的自动机的答案加在一起即可
TIPS:不能把\(fail\)边直接作为子节点来建图,因为之后还要加字符串进去
//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5e6+7;
class ACautomaton{
private:
int fail[MAXN],ch[MAXN][2],tot,last[MAXN],cnt[MAXN];
queue<int> que;
bool updated;
void buildfail(){
for(int i = 0; i < 2; i++){
if(!ch[0][i]) continue;
que.push(ch[0][i]);
fail[ch[0][i]] = last[ch[0][i]] = 0;
}
while(!que.empty()){
int u = que.front();
que.pop();
for(int c = 0; c < 2; c++){
int v = ch[u][c];
if(!v) continue;
int p = fail[u];
while(p and !ch[p][c]) p = fail[p];
fail[v] = ch[p][c];
last[v] = cnt[fail[v]]?fail[v]:last[fail[v]];
que.push(v);
}
}
}
public:
void clear(){
for(int i = 0; i <= tot; i++){
ch[i][0] = ch[i][1] = 0;
cnt[i] = 0;
}
tot = 0; updated = false;
}
void insert(char *s){
updated = true;
int now = 0;
for(int i = 0; s[i]; i++){
int c = s[i] - '0';
if(!ch[now][c]) ch[now][c] = ++tot;
now = ch[now][c];
}
cnt[now] = 1;
}
int mt(int u){
int ret = 0;
while(u){
ret += cnt[u];
u = last[u];
}
return ret;
}
int match(char *s){
if(updated) buildfail();
updated = false;
int ret = 0, now = 0;
for(int i = 0; s[i]; i++){
int c = s[i] - '0';
while(now and !ch[now][c]) now = fail[now];
now = ch[now][c];
ret += mt(now);
}
return ret;
}
int size(){ return tot; }
void merge(ACautomaton &rhs, int u, int v){
updated = true;
for(int c = 0; c < 2; c++){
if(!rhs.ch[v][c]) continue;
if(!ch[u][c]) ch[u][c] = ++tot;
merge(rhs,ch[u][c],rhs.ch[v][c]);
}
cnt[u] |= rhs.cnt[v];
}
}aho[2];
char s[MAXN],t[MAXN];
void solve(int kase){
printf("Case #%d:\n",kase);
aho[0].clear(); aho[1].clear();
int lastres = 0, q;
scanf("%d",&q);
int up = sqrt(MAXN);
while(q--){
scanf("%s",s);
int len = strlen(s+1);
int shift = lastres % len;
t[len] = '\0';
for(int i = 0; i < len; i++) t[i] = s[(i+shift)%len+1];
if(s[0]=='?') printf("%d\n",lastres=aho[0].match(t)+aho[1].match(t));
else{
aho[1].insert(t);
if(aho[1].size()>up){
aho[0].merge(aho[1],0,0);
aho[1].clear();
}
}
}
}
int main(){
int T; scanf("%d",&T);
for(int kase = 1; kase <= T; kase++) solve(kase);
return 0;
}
HDU4787 GRE Words Revenge【AC自动机 分块】的更多相关文章
- GRE Words Revenge AC自动机 二进制分组
GRE Words Revenge 题意和思路都和上一篇差不多. 有一个区别就是需要移动字符串.关于这个字符串,可以用3次reverse来转换, 前面部分翻转一下, 后面部分翻转一下, 最后整个串翻转 ...
- [HDU 4787] GRE Words Revenge (AC自动机)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4787 题目大意: 给你若干个单词,查询一篇文章里出现的单词数.. 就是被我水过去的...暴力重建AC自 ...
- HDU 3341 Lost's revenge AC自动机+dp
Lost's revenge Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
- HDU4787 GRE Words Revenge(AC自动机 分块 合并)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4787 Description Now Coach Pang is preparing for ...
- 【CF587F】Duff is Mad AC自动机+分块
[CF587F]Duff is Mad 题意:给出n个串$s_1,s_2..s_n$,有q组询问,每次给出l,r,k,问你编号在[l,r]中的所有串在$s_k$中出现了多少次. $\sum|s_i|, ...
- hdu 4117 GRE Words (ac自动机 线段树 dp)
参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...
- HDU-4787 GRE Words Revenge 解题报告
这是我之前博客里提到的一道AC自动机的练手题,但是要完成这道题,我之前博客里提到的东西还不够,这里总结一下这道题. 这道题不是一般的裸的AC自动机,它的询问和插入是交叉出现的所以用我之前写的板子不大合 ...
- [HDU4787]GRE Words Revenge 解题报告
这是我之前博客里提到的一道AC自动机的练手题,但是要完成这道题,我之前博客里提到的东西还不够,这里总结一下这道题. 这道题不是一般的裸的AC自动机,它的询问和插入是交叉出现的所以用我之前写的板子不大合 ...
- HDU3341 Lost's revenge(AC自动机&&dp)
一看到ACGT就会想起AC自动机上的dp,这种奇怪的联想可能是源于某道叫DNA什么的题的. 题意,给你很多个长度不大于10的小串,小串最多有50个,然后有一个长度<40的串,然后让你将这个这个长 ...
随机推荐
- 串的模式匹配算法1 BF算法
BF算法 字符串的模式匹配不一定要从主串的第一个位置开始,可以指定主串中查找的起始位置 pos. 2. 算法步骤: 1)分别利用计数器指针 i 和 j 指定主串和模式串即小字符串待比较的位置,初始化为 ...
- 【RAC】Oracle 10g RAC相关启停命令,维护命令
Oracle10g RAC关闭及启动步骤 情况1:需要关闭DB(所有实例),OS及Server. a.首先停止Oracle10g环境 $ lsnrctl stop (每个节点上停止监听,也可以用s ...
- 工作记录:记一次线上ZK掉线问题排查
目录 问题的发现 zk的情况以及分析 总结 问题的发现 最早问题的发现在于用户提的,用户提出他支付时支付失败,过了一会儿再试就好了,于是翻日志,查询到当时duboo调用出现了下类错误: [TraceI ...
- oracle分区表分区栏位NULL值测试
实验在分区栏位为NULL时,分区表的反应 1.创建普通的分区表 CREATE TABLE MONKEY.TEST_PART_NULL_NORMAL ( ID NUMBER, ADD_DATE DATE ...
- 微软官网下载win10离线介质
1.打开google浏览器 2.搜索win10官网下载或者直接输入网址https://www.microsoft.com/zh-cn/software-download/windows10 3.按F1 ...
- 一个div画同心圆
二话不说上代码 background-image:radial-gradient(7px,#00A4FF 50%,#fff 75%,#00A4FF 94%); 7px是圆的半径 效果:
- Java 栈的使用
讲栈之前,要先讲一下Deque双端队列 既可以添加到队尾,也可以添加到队首 既可以从队首获取又可以从队尾获取 public interface Deque<E> extends Queue ...
- Mybatis入门Demo(单表的增删改查)
1.Mybatis 什么是Mybatis: mybatis是一个持久层框架,用java编写的 它封装了jdbc操作的很多细节,使开发者只需要关注sql语句本身,而无需关注注册驱动.创建连接等繁杂过程 ...
- css-前端实现左中右三栏布局的常用方法:绝对定位,圣杯,双飞翼,flex,table-cell,网格布局等
1.前言 作为一个前端开发人员,工作学习中经常会遇到快速构建网页布局的情况,这篇我整理了一下我知道的一些方法.我也是第一次总结,包括圣杯布局,双飞翼布局,table-cell布局都是第一次听说,可能会 ...
- SpringCloud Alibaba Nacos注册中心源码浅析
一.前置了解 1.1 简介 Nacos是一款阿里巴巴推出的一款微服务发现.配置管理框架.我们本次对将对它的服务注册发现功能进行简单源码分析. 1.2 流程 Nacos的分析分为两部分,一部分是我们的客 ...