题意:

给定T个测试数据

n个操作

+ 插入单词

? 询问母串中有多少个子串 在上面出现过

( 子串被加密,即←移动L位 (L为上次询问的答案) )

分块思路:

因为模式串和母串交叉给出,正常来说应该是,每次询问前都要getFail,这样显然会超时)

所以我们用一个小型ac自动机 buf , 每次插入都插入到 buf 中,并重建一下buf 的getFail

若buf的节点数 > 2000,则把其中节点添加到 ac自动机上

时间复杂度为 O(n*sqrt(n)) ,详见tao哥题解:http://blog.csdn.net/no__stop/article/details/16823479

geiFail一次 时间为 当前自动机上的节点数

#pragma comment( linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define maxnode 511111
#define sigma_size 2
struct Trie{
int ch[maxnode][sigma_size];
bool val[maxnode];
int f[maxnode];
int sz;
void init(){
sz=1;
memset(ch,0,sizeof(ch));
memset(val, 0, sizeof(val));
memset(f,0,sizeof(f));
}
int idx(char c){ return c-'0'; }
int insert(char *s){
int u = 0;
for(int i = 0; s[i] ;i++){
int c = idx(s[i]);
if(!ch[u][c])
ch[u][c] = sz++;
u = ch[u][c];
}
val[u] = 1;
return u;
}
bool search(char *s){
int u = 0;
for(int i = 0; s[i] ;i++){
int c = idx(s[i]);
if(!ch[u][c]) return 0;
u = ch[u][c];
}
return val[u];
}
void getFail(){
queue<int> q;
for(int i = 0; i<sigma_size; i++)
if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()){
int r = q.front(); q.pop();
for(int c = 0; c<sigma_size; c++){
int u = ch[r][c];
if(!u)continue;
q.push(u);
int v = f[r];
while(v && ch[v][c] == 0) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
f[u] = ch[v][c];
}
}
}
int find(char *T){
int j = 0, ans = 0;
for(int i = 0; T[i] ; i++){
int c = idx(T[i]);
while(j && ch[j][c]==0) j = f[j];
j = ch[j][c];
int temp = j;
while(temp){ //沿失配边走 || 若沿失配边走时一定要节点为单词结尾则改成while(temp && val[temp])
ans += val[temp];
temp = f[temp];
}
}
return ans;
}
};
Trie ac, buf;
void dfs(int u, int v){
for(int i = 0;i < 2;i++){
if( buf.ch[v][i] )
{
int e2 = buf.ch[v][i];
if(! ac.ch[u][i])
{
memset(ac.ch[ac.sz], 0, sizeof(ac.ch[ac.sz]));
ac.ch[u][i] = ac.sz++;
}
int e1 = ac.ch[u][i];
ac.val[e1] |= buf.val[e2];
dfs(e1, e2);
}
}
}
void join(){
dfs(0, 0);
buf.init();
ac.getFail();
}
char s[6000000],temp[6000000];
int main(){
int Cas = 1, T, n;scanf("%d",&T);
while(T--){
scanf("%d",&n);
printf("Case #%d:\n",Cas++);
ac.init();
buf.init();
int L = 0;
while(n--){
scanf("%s",temp);
int len = strlen ( temp + 1 ) ;
s[0] = temp[0] ;
for (int i = 0 ; i < len ; i ++ )
s[i+1] = temp[1+(i+L%len+len)%len] ;
s[len+1] = '\0';
if(s[0] == '+'){
if( buf.search(s+1) || ac.search(s+1) )continue;//若单词已存在
buf.insert(s+1);
buf.getFail();
if(buf.sz > 2000) join();
}
else
{
L = buf.find(s+1) + ac.find(s+1);
printf("%d\n", L);
}
}
}
return 0;
}
/*
/*
99
10
+01
+110
?010
+110
+00
+0
?001001
?001001
+110110
?1101001101
6
+01
+110
+110
+00
+0
?001001
20
+101001011
?110100
+11010100
?0011001101
+111011
?00010011
+0111010110
+0000101
+0
+11000
?1
+1010101
+0001
+0110
+0111101111
?1100
+0111
+1001
?0110111011
?1010010100
10
+00
?010110100
+0100000100
+111
+000000
?0000110
+110
+00
+0011
?101001
99
+0
+1000100
+01
+0
?1110010011
ans:
case 1
1
7
7
11
case 2
8
*/

HDU 4787 在线AC自动机 分块(模式串和母串交叉给出,多次求getFail)相关推荐

  1. AC自动机 - 多模式串的匹配 --- HDU 3695 Computer Virus on Planet Pandora

    Problem's Link Mean: 有n个模式串和一篇文章,统计有多少模式串在文章中出现(正反统计两次). analyse: 好久没写AC自动机了,回顾一下AC自动机的知识. 本题在构造文章的时 ...

  2. Keywords Search HDU - 2222(AC自动机模板)

    题意: 给定 n个长度不超过 50的由小写英文字母组成的单词准备查询,以及一篇文章,问:文中出现了多少个待查询的单词.多组数据. 题目: In the modern time, Search engi ...

  3. HDU 2296 Ring AC自动机 + DP

    题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串 ...

  4. hdu 6096---String(AC自动机)

    题目链接 Problem Description Bob has a dictionary with N words in it. Now there is a list of words in wh ...

  5. HDU - 2296 Ring(AC自动机+dp)

    题目链接:点击查看 题目大意:给出 n 个字符串,每个字符串都有一个权值,现在问在组成字符串长度不超过 m 的前提下,怎样构造才能使得出现的字符串权值和最大,在满足上个条件的基础上长度最短,如果依然有 ...

  6. hdu 2604 Queuing AC自动机构造递推式-矩阵-结果

    http://acm.hdu.edu.cn/showproblem.php?pid=2604 题意: L个人排队,这一队里男性用m表示,女性用f表示,问长度为L的序列里面不包含形如"fmf& ...

  7. HDU 3058 Generator [AC自动机+期望DP]

    给出M个短串,这些短串由前N个大写字母组成.然后随机的按字符生成字符串,每次生成1~N个字符的概率是相等的,当生成串包含任意一个指定短串时,就停止生成.问生成串的长度的期望是多少. 首先建立Trie图 ...

  8. hdu 2896 病毒侵袭(AC自动机)

    病毒侵袭                                                                           Time Limit: 2000/1000 ...

  9. AC自动机:多模式串匹配实现敏感词过滤

    文章出处:极客时间<数据结构和算法之美>-作者:王争.该系列文章是本人的学习笔记. 1 敏感词过滤场景 在很多支持用户发表内容的网站,都有敏感词过滤替换的功能.例如将一些淫秽.反动内容过滤 ...

最新文章

  1. linux意外重启分析,Linux关机重启流程分析
  2. java计算5 5_Java基础学习笔记 -- 5(运算符)
  3. 要做linux运维工程师的朋友,必须要掌握以下几个工具才行
  4. 使用API获得SAP CRM Sales Area数据
  5. [silverlight基础]仿文字连接跑马灯效果-高手绕道
  6. [urllib]urlretrieve在python3
  7. PHP程序中时间戳,php 时间戳常用代码
  8. git 拉取 未能顺利结束 (退出码 1)_小白的 asyncio :原理、源码 到实现(1)
  9. php脚本语法格式,[PHP学习笔记][五]PHP基本语法规则
  10. Oracle查看表空间使用率及爆满解决方案
  11. 谷歌浏览器插件 清除 CSDN广告
  12. linux系统刷机教程,在 Linux 刷 BIOS
  13. IPV4怎么转换成IPV6?
  14. 字节跳动岗位薪酬体系曝光,看完感叹:我酸了
  15. 台湾大学林轩田机器学习技法课程学习笔记8 -- Adaptive Boosting
  16. android pie mi 3 tab,前沿科技:三星Galaxy Tab S3和Tab A(2017)正在获得Android 9.0 Pie更新
  17. 【开发教程14】AI语音人脸识别(会议记录仪/人脸打卡机)-AI人脸系统架构
  18. 专访阿里巴巴量子实验室:最强量子电路模拟器“太章”到底强在哪? 1
  19. Whitelabel Error Page并且报500
  20. EasyMesh - A Two-Dimensional Quality Mesh Generator

热门文章

  1. react高阶组件的使用
  2. win10系统隐藏u盘EFI分区的方法
  3. Word控件Spire.Doc 转换教程(十三):在word文档和HTML中嵌入图像支持
  4. Android怎么查阅官方的开发者文档(How to browse Android official Docs)
  5. 高级 markdown 编辑器的惊艳语法
  6. c语言 找子字符串,c语言搜索子字符串
  7. 5.5寸2k彩屏3d打印机chitubox尺寸设置
  8. JavaScript漂浮的气球
  9. Oracle数据库迁移到MySQL数据库
  10. 项目Beta冲刺(团队)——总结篇