HDU4787_GRE Words Revenge
这个题目做得泪牛满面。
题目为给你若干串,有的表示添加一个串,有的表示询问一个串有多少个字串为前面出现过的串。
题目一看就知道肯定是AC自动机(不过后缀自动机也是可以的)
但是细想就会发现AC自动机好像不支持在线修改。如果你每次读入一个串就重构一次AC自动机的话,那么时间复杂度达到了N^2,肯定会T的。
于是就产生了一种奇葩的解法。
搞两个自动机,一个自动机为大的自动机,一个自动机为小的自动机(用于缓冲)。每次我都只把字符串加入到小的自动机里面并且重构小自动机,当小自动机的容量超过了sqrt(L)的时候,我们把小自动机合并到大自动机上,这样算下来时间复杂度为O(L*sqrt(L)),每次询问的答案就是大小自动机上查询答案的和,好像是可以AC的。
但是问题来了,怎么合并两个自动机呢?
其实很简单,自动机相对于字典树来说有什么区别呢?一个是tire树,一个是tire图,自动机多了fail指针还多了一些新建立的next指针。所以我们只要把这些多余的指针去掉,然后对小字典树做一次搜索就可以吧两个字典树合并了。然后重构了一次大自动机,小自动机清空,就可以了。
总的时间复杂度有点勉强,不过算下来10^5好像理论上来说也是可以过的。
赞一个,题目出的太好了。
不过听说还有用后缀自动机做,并且用动态树来维护的。不明觉厉啊。求神犇指点。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define maxn 100050
using namespace std; int next[][maxn][],has[][maxn][],tag[][maxn],sum[][maxn],fail[][maxn],N[];
char s0[*maxn],s[*maxn];
int qx[maxn],qy[maxn],tq;
int ans,n,t; int add(int x)
{
N[x]++;
next[x][N[x]][]=next[x][N[x]][]=;
has[x][N[x]][]=has[x][N[x]][]=;
tag[x][N[x]]=;
sum[x][N[x]]=;
fail[x][N[x]]=;
return N[x];
} void init(int x)
{
N[x]=-;
N[x]=add(x);
} void initall()
{
ans=;
init(),init();
} void getstring()
{
scanf("%s",s0);
int L=strlen(s0)-,cur=;
for (int i=ans%L+; s0[i]; i++) s[cur]=s0[i],cur++;
for (int i=; i<=ans%L; i++) s[cur]=s0[i],cur++;
s[L]=;
} void destory(int x)
{
for (int i=; i<=N[x]; i++)
{
fail[x][i]=;
for (int j=; j<; j++)
if (has[x][i][j]==) next[x][i][j]=;
}
} void insert()
{
int cur=,tep;
for (int i=; s[i]; i++)
{
tep=s[i]-'';
if (next[][cur][tep]==)
{
next[][cur][tep]=add();
has[][cur][tep]=;
}
cur=next[][cur][tep];
}
tag[][cur]=;
} void union01()
{
int cur=;
qx[]=qy[]=;
while (cur>)
{
int xx=qx[cur],yy=qy[cur];
if (tag[][yy]) tag[][xx]=;
cur--;
for (int i=; i<; i++)
{
if (next[][yy][i])
{
if (next[][xx][i]==)
{
next[][xx][i]=add();
has[][xx][i]=;
}
cur++;
qx[cur]=next[][xx][i];
qy[cur]=next[][yy][i];
}
}
}
} void AC_build(int x)
{
for (int i=; i<=N[x]; i++) sum[x][i]=tag[x][i];
queue<int> Q;
int cur,child;
Q.push();
while (!Q.empty())
{
cur=Q.front(),Q.pop();
for (int i=; i<; i++)
{
child=next[x][cur][i];
if (child)
{
Q.push(child);
if (cur==) fail[x][child]=;
else
{
fail[x][child]=next[x][fail[x][cur]][i];
sum[x][child]+=sum[x][fail[x][child]];
}
}
else next[x][cur][i]=next[x][fail[x][cur]][i];
}
}
} int query(int x)
{
int cur=,tep,tot=;
for (int i=; s[i]; i++)
{
tep=s[i]-'';
cur=next[x][cur][tep];
tot+=sum[x][cur];
}
return tot;
} bool find(int x)
{
int cur=,tep;
for (int i=; s[i]; i++)
{
tep=s[i]-'';
if (has[x][cur][tep]) cur=next[x][cur][tep];
else return false;
}
if (tag[x][cur]==) return false;
return true;
} int main()
{
int cas=;
scanf("%d",&t);
while (t--)
{
printf("Case #%d:\n",++cas);
initall();
scanf("%d",&n);
while (n--)
{
getstring();
if (s0[]=='+')
{
if (find() || find()) continue;
destory();
insert();//insert s to trie 1
if (N[]>=)
{
destory();
union01();
AC_build();
init();
}
else AC_build();
}
else if (s0[]=='?')
{
ans=query()+query();
printf("%d\n",ans);
}
}
}
return ;
}
HDU4787_GRE Words Revenge的更多相关文章
- 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 ...
- HDU 5019 Revenge of GCD(数学)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5019 Problem Description In mathematics, the greatest ...
- L - Abbott's Revenge(比较复杂的bfs)
Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Status Practice UV ...
- hdu 4099 Revenge of Fibonacci 大数+压位+trie
最近手感有点差,所以做点水题来锻炼一下信心. 下周的南京区域赛估计就是我的退役赛了,bless all. Revenge of Fibonacci Time Limit: 10000/5000 MS ...
- HDU5088——Revenge of Nim II(高斯消元&矩阵的秩)(BestCoder Round #16)
Revenge of Nim II Problem DescriptionNim is a mathematical game of strategy in which two players tak ...
- HDU5087——Revenge of LIS II(BestCoder Round #16)
Revenge of LIS II Problem DescriptionIn computer science, the longest increasing subsequence problem ...
- HDU5086——Revenge of Segment Tree(BestCoder Round #16)
Revenge of Segment Tree Problem DescriptionIn computer science, a segment tree is a tree data struct ...
- UVA 816 - Abbott's Revenge(BFS)
UVA 816 - Abbott's Revenge option=com_onlinejudge&Itemid=8&page=show_problem&category=59 ...
- hdu 4099 Revenge of Fibonacci Trie树与模拟数位加法
Revenge of Fibonacci 题意:给定fibonacci数列的前100000项的前n位(n<=40);问你这是fibonacci数列第几项的前缀?如若不在前100000项范围内,输 ...
随机推荐
- #2017-2018-1 20155327 《信息安全系统设计基础》实现mypwd
2017-2018-1 20155327 <信息安全系统设计基础>实现mypwd Linux pwd命令用于显示工作目录. 执行pwd指令可立刻得知您目前所在的工作目录的绝对路径名称. p ...
- 20155329实验二 Java面向对象程序设计
实验二 Java面向对象程序设计 1实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 2. 初步掌握单元测试 ...
- adb的配置
http://jingyan.baidu.com/article/2fb0ba405e815f00f2ec5f9e.html 1. 用快捷键Ctrl + Alt + T 打开终端命令工具,电脑不要插入 ...
- MySql数据的插入-replace into
一.新的数据插入方式:REPLACE INTO mysql中常用的插入方式:INSERT INTO 如果要插入不重复的数据的方式:REPLACE INTO 二.二者比较: replace into 首 ...
- [BZOJ3218]a + b Problem-[主席树+网络流-最小割]
Description 传送门 Solution 此处我们按最小割的思路考虑. 暴力:S->i表示该点选黑色的权值b[i]:i->T表示该点选白色的权值w[i].考虑如果某个点i受点j为白 ...
- C#:通过NuGet程序包下载CefSharp来加载谷歌浏览器
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 首先我讲明一下我要做的,公司有个C# wpf的项目需要我把一个开发好的网页嵌入到客户端当中,由于种种原因,我放 ...
- katalon系列十五:给浏览器添加cookie自动登陆
import org.openqa.selenium.Cookieimport org.openqa.selenium.WebDriverimport com.kms.katalon.core.web ...
- 【转载】IntelliJ IDEA 2017常用快捷键
IntelliJ IDEA 是一款致力于提供给开发工程师沉浸式编程体验的IDE工具,所以在其中提供了很多方便高效的快捷键,一旦熟练掌握,整个开发的效率和体验将大大提升.本文就按照笔者自己日常开发时的使 ...
- 算法与AI的暗黑面:3星|《算法的陷阱:超级平台、算法垄断与场景欺骗》
算法的陷阱:超级平台.算法垄断与场景欺骗 全书讲算法与AI的暗黑面:价格歧视.导致算法军备竞赛.导致商家降价冲动降低.平台作恶(向劣质商家收费导致品质下降.与开发商一起分析用户隐私)等. 作者从商业. ...
- cs231n学习笔记(一)计算机视觉及其发展史
在网易云课堂上学习计算机视觉经典课程cs231n,觉得有必要做个笔记,因为自己的记性比较差,留待以后查看. 每一堂课都对应一个学习笔记,下面就开始第一堂课. 这堂课主要是回顾了计算机视觉的起源及其后来 ...