【二进制分组+AC自动机】HDU4787[GRE Words Revenge]题解
来源:互联网 发布:网络摄像机厂家 编辑:程序博客网 时间:2024/05/17 10:28
题目概述
给出
解题报告
如果是插入完再询问,就是AC自动机裸题。如果不强制在线,可以按照时间分治。
然而都不满足啊,只能另想办法了。又一个神奇的暴力,二进制分组就派上用场了。
每次插入都必须重建AC自动机,但是这是无法承受的。我们将插入分组,如果这一组与上一组的个数相同,那么就将两者合并,并重建AC自动机。
差不多是这样:
11 1 -> 22 12 1 1 -> 2 2 -> 4
因为每个串所在组的大小每次
最后在每个组(至多
示例程序
因为实在不怎么相信string的速度QAQ,所以写了很奇怪的字符数组,并且用了set+hash判重。
#include<cstdio>#include<cctype>#include<cstring>#include<set>using namespace std;typedef long long LL;typedef unsigned long long ULL;const int maxn=1e5,maxl=5e6,Ba=3214567;int te,Q;char s[maxl+5];LL lstans;int n,pos,str[maxn+5];char tem[maxl+maxn+5];int len,son[maxl+5][2],fai[maxl+5],num[maxn+5];int blk,si[maxn+5],ro[maxn+5],que[maxn+5];set<ULL> f;#define Eoln(x) ((x)==10||(x)==13||(x)==EOF)inline char readc(){ static char buf[100000],*l=buf,*r=buf; if (l==r) r=(l=buf)+fread(buf,1,100000,stdin); if (l==r) return EOF;return *l++;}inline int readi(int &x){ int tot=0,f=1;char ch=readc(),lst='+'; while (!isdigit(ch)) {if (ch==EOF) return EOF;lst=ch;ch=readc();} if (lst=='-') f=-f; while (isdigit(ch)) tot=(tot<<3)+(tot<<1)+ch-48,ch=readc(); return x=tot*f,Eoln(ch);}inline char getfst() {char ch=readc();while (ch!='+'&&ch!='?') ch=readc();return ch;}inline int reads(char *s){ int len=0;char ch=readc();if (ch==EOF) return EOF; s[++len]=ch;while (isdigit(s[len])) s[++len]=readc(); return s[len--]=0,len;}inline void Build(int ro){ int Head=0,Tail=0,u; for (int i=0;i<2;i++) if (u=son[ro][i]) que[++Tail]=u,fai[u]=ro; else son[ro][i]=ro; while (Head!=Tail) { int x=que[++Head];num[x]+=num[fai[x]]; for (int i=0;i<2;i++) if (u=son[x][i]) que[++Tail]=u,fai[u]=son[fai[x]][i]; else son[x][i]=son[fai[x]][i]; }}#define S(i) (tem+str[i])inline char* Add(char *s,char f){ int len=strlen(s+1);str[++n]=pos;S(n)[len+1]=0; for (int i=1;i<=len;i++) S(n)[i]=s[(i+lstans-1)%len+1]; if (f=='+') return pos+=len+1,S(n); else return S(n--);}#define newnode (len++,son[len][0]=son[len][1]=fai[len]=num[len]=0,len)inline void Insert(char *s){ ULL Ha=0;for (int i=1;s[i];i++) Ha=Ha*Ba+s[i];if (f.count(Ha)) {n--;return;} for (si[++blk]=1;blk>1&&si[blk]==si[blk-1];len=ro[--blk]-1) si[blk-1]+=si[blk]; ro[blk]=newnode;f.insert(Ha); for (int i=n-si[blk]+1;i<=n;i++) { int p=ro[blk]; for (int j=1;S(i)[j];j++) {int &u=son[p][S(i)[j]-'0'];if (!u) u=newnode;p=u;} num[p]=1; } Build(ro[blk]);}inline LL Ask(char *s){ lstans=0; for (int i=1;i<=blk;i++) for (int j=1,p=ro[i];s[j];j++) p=son[p][s[j]-'0'],lstans+=num[p]; return lstans;}int main(){ freopen("program.in","r",stdin); freopen("program.out","w",stdout); for (int i=(readi(te),1);i<=te;i++,lstans=0,f.clear()) { printf("Case #%d:\n",i);n=0;pos=0;blk=0;len=0; for (readi(Q);Q;Q--) { char td=getfst();reads(s); if (td=='+') Insert(Add(s,td)); else printf("%lld\n",Ask(Add(s,td))); } } return 0;}
阅读全文
0 0
- 【二进制分组+AC自动机】HDU4787[GRE Words Revenge]题解
- [二进制分组+AC自动机] HDU4787 GRE Words Revenge
- [阈值 二进制分组 && AC自动机]HDU4787. GRE Words Revenge
- HDU4787--GRE Words Revenge(在线AC自动机)
- 【HDU4787】GRE Words Revenge【AC自动机】【AC自动机合并】
- [二进制分组 AC自动机] HDU 4787 GRE Words Revenge
- hdu4787 GRE Words Revenge,AC自动机,平方分割
- hdu4787 GRE Words Revenge
- [ AC自动机 二进制分组/阈值 ] HDU4787
- HDU 4787 GRE Words Revenge AC自动机
- hdu 4787 GRE Words Revenge(AC自动机)
- hdu 4787 GRE Words Revenge (在线AC自动机)
- hdu 4787 GRE Words Revenge(分块+AC自动机)
- HDU 4787 GRE Words Revenge(在线AC自动机)
- HDU 4787 GRE Words Revenge 在线AC自动机
- hdu 4787 GRE Words Revenge(在线AC自动机)
- HDOJ 题目4787 GRE Words Revenge(在线ac自动机,离线也可做)
- HDU 4787 GRE Words Revenge(在线AC自动机)★ ★
- USB通信协议
- struts2 --- 拦截器
- 中企动力小程序开发服务上市,4大核心功能支持全行业
- 对动态规划DP的深入理解
- Java并发编程规则:判定对象是否存在多线程访问
- 【二进制分组+AC自动机】HDU4787[GRE Words Revenge]题解
- 给c++跪了.cpp
- 【IDEA Intel 输入法】Android Studio ,和 PhpStorm ,修复中文输入法,运用了两套 jre64 工具来解决。
- shell脚本-复制root目录下所有目录到tmp/下
- Centos搭建持续集成(六)----安装Maven以及nexus3私服
- Android 绘制顺序
- 【重装ubuntu16.04】一些细节
- centos 安装 grpc
- 免费GIS数据下载网站推荐