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自动机 分块】的更多相关文章

  1. GRE Words Revenge AC自动机 二进制分组

    GRE Words Revenge 题意和思路都和上一篇差不多. 有一个区别就是需要移动字符串.关于这个字符串,可以用3次reverse来转换, 前面部分翻转一下, 后面部分翻转一下, 最后整个串翻转 ...

  2. [HDU 4787] GRE Words Revenge (AC自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4787 题目大意: 给你若干个单词,查询一篇文章里出现的单词数.. 就是被我水过去的...暴力重建AC自 ...

  3. 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 ...

  4. HDU4787 GRE Words Revenge(AC自动机 分块 合并)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4787 Description Now Coach Pang is preparing for ...

  5. 【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|, ...

  6. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  7. HDU-4787 GRE Words Revenge 解题报告

    这是我之前博客里提到的一道AC自动机的练手题,但是要完成这道题,我之前博客里提到的东西还不够,这里总结一下这道题. 这道题不是一般的裸的AC自动机,它的询问和插入是交叉出现的所以用我之前写的板子不大合 ...

  8. [HDU4787]GRE Words Revenge 解题报告

    这是我之前博客里提到的一道AC自动机的练手题,但是要完成这道题,我之前博客里提到的东西还不够,这里总结一下这道题. 这道题不是一般的裸的AC自动机,它的询问和插入是交叉出现的所以用我之前写的板子不大合 ...

  9. HDU3341 Lost's revenge(AC自动机&&dp)

    一看到ACGT就会想起AC自动机上的dp,这种奇怪的联想可能是源于某道叫DNA什么的题的. 题意,给你很多个长度不大于10的小串,小串最多有50个,然后有一个长度<40的串,然后让你将这个这个长 ...

随机推荐

  1. 离散傅里叶变换DFT入门

    网上对于傅里叶变换相关的文章很多(足够多),有的是从物理相关角度入场,有的从数学分析角度入场.对于有志学习相关概念的同学还是能够很好的理解的. 数学包括三大块:代数学.几何.数学分析.前两块我们在中学 ...

  2. ClickHouse安装使用(单机、集群、高可用)

    Clickhouse版本:20.3.6.40-2 安装包地址:https://repo.yandex.ru/clickhouse/rpm/stable/x86_64/ 一.单机版 1.安装依赖 yum ...

  3. Loadrunner录制脚本与编写脚本的区别

    异同点: 1.录制的和编写的脚本质量上没有区别 2.性能脚本关心的是用户和服务器的数据交互,从这点上来看,录制和编写也没有区别,手动编写脚本也可以写出很真实的脚本 3.能录制的情况下,就录制吧,谁每天 ...

  4. Kafka 探险 - 生产者源码分析: 核心组件

    这个 Kafka 的专题,我会从系统整体架构,设计到代码落地.和大家一起杠源码,学技巧,涨知识.希望大家持续关注一起见证成长! 我相信:技术的道路,十年如一日!十年磨一剑! 往期文章 Kafka 探险 ...

  5. nmap的理解与利用(初级)

    在命令窗口下输入命令等待,可以用回车来查看进度 nmap进行探测之前要把域名通过dns服务器解析为ip地址,我们也可以使用指定的dns服务器进行解析. nmap --dns-servers 主机地址 ...

  6. 【Android】关于连续多次点击控件的控制方案(新建监听类)

    参考:防止Android过快点击造成多次事件的三种方法_胖胖的博客-CSDN博客 实现逻辑很简单: 设置限定时间 在用户点击时开始计时 若计时未超过限定时间,则不允许触发点击事件 因还未学习过Rxja ...

  7. LocalDateTime、OffsetDateTime、ZonedDateTime互转,这一篇绝对喂饱你

    前言 你好,我是A哥(YourBatman). 在JSR 310日期时间体系了,一共有三个API可用于表示日期时间: LocalDateTime:本地日期时间 OffsetDateTime:带偏移量的 ...

  8. 使用pushplus+python实现亚马逊到货消息推送微信

    xbox series和ps5发售以来,国内黄牛价格一直居高不下.虽然海外amazon上ps5补货很少而且基本撑不过一分钟,但是xbox series系列明显要好抢很多. 日亚.德亚的xbox ser ...

  9. fiddler安装以及使用说明

    一.fiddler fiddler是一个抓包工具,通过使用它抓包我们可以很清晰的看到抓的内容的协议,URL,参数等. 1.安装 在普通下载网站找到安装包,直接安装,点击下一步即可. 二.使用 1.se ...

  10. Hugo 博客中文指南(基础教程)

    1. 安装 Hugo 从 Hugo 项目主页下载 Releases 文件,解压 hugo.exe 文件到 C:\Windows\System32 目录下. 2. 创建站点 hugo new site ...