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. 【MyBatis】MyBatis 连接池和事务控制

    MyBatis 连接池和事务控制 文章源码 MyBaits 连接池 实际开发中都会使用连接池,因为它可以减少获取连接所消耗的时间.具体可查看 MyBatis 数据源配置在 SqlMapConfig.x ...

  2. 天梯赛练习 L3-011 直捣黄龙 (30分) dijkstra + dfs

    题目分析: 本题我有两种思路,一种是只依靠dijkstra算法,在dijkstra部分直接判断所有的情况,以局部最优解得到全局最优解,另一种是dijkstra + dfs,先计算出最短距离以及每个点的 ...

  3. mac配置Android SDK

    下载地址:http://tools.android-studio.org/index.php/sdk 2.找到tools文件夹 选中android-sdk-macosx包下的tools文件夹,按com ...

  4. Java JDBC的 url 配置信息和Mybatis核心配置文件(MySQL 的配置信息)

    JDBC 连接数据库的 url driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/smbms?uesSSL=true&u ...

  5. IDEA 常用的一些 (就几个) 快捷键

    快捷键 说明 Ctrl + P 提示类参数 Ctrl + Q 提示类的属性和方法包名 Ctrl + D 复制一行到下一行 Ctrl + F 查找 Ctrl + R 替换 Ctrl + Z 撤销 Ctr ...

  6. ctfhub技能树—信息泄露—hg泄露

    打开靶机 查看页面信息 使用dvcs-ripper工具进行处理 ./rip-hg.pl -v -u http://challenge-cf630b528f6f25e2.sandbox.ctfhub.c ...

  7. odoo之技巧合集一

    罗列一些odoo开发中的简单但有效的方法: 1.重写odoo登录代码 参考链接:odoo10-重写登录方法 from odoo import models, fields, api, SUPERUSE ...

  8. watchdog应用实例

    watchdog应用实例 By 鬼猫猫 20130504 http://www.cnblogs.com/muyr/ 实例:监测某文件夹,一旦文件夹里有文件,就把它剪切到其他服务器 import sys ...

  9. Redisson 分布式锁实战与 watch dog 机制解读

    Redisson 分布式锁实战与 watch dog 机制解读 目录 Redisson 分布式锁实战与 watch dog 机制解读 背景 普通的 Redis 分布式锁的缺陷 Redisson 提供的 ...

  10. 获取Java线程转储的常用方法

    1. 线程转储简介 线程转储(Thread Dump)就是JVM中所有线程状态信息的一次快照. 线程转储一般使用文本格式, 可以将其保存到文本文件中, 然后人工查看和分析, 或者使用工具/API自动分 ...