一道叉姐的AC自动机鬼题
题面描述丢失了。。。
给n个串模板串,然后再给你m个串,对于这m个串的每个串,问在[L,R]的模板串中,在多少个串中出现过;
这题的正解是对于后m个串建AC自动机,然后离线,在fail树上树链求并。
然而我想脑抽地打一下后缀数组;
如果用后缀数组的话,跟喵星球上的点名差不多,但是要在[L,R]中,所以可以用Gty的二逼妹子序列一样的套路,把权值分块而不用树状数组;
这样可以做到nsqrt(n);但是由于串有几百万长,求SA就T了。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define RG register
using namespace std;
const int N=2000050;
struct data{
int fir,sec,id;
}x[N];
bool cmp(const data &a,const data &b){
if(a.fir==b.fir) return a.sec<b.sec;
else return a.fir<b.fir;
}
int y[N],sa[N],height[N],rnk[N],rk,n,m,len;
int pos[N],fr[N],bel[N],blockans[N],sum[N],st[N],block,block2,L[N],R[N],pre[N],pre2[N],ST[N][21];
int ans[N],lo[N],tong[N],g[N],cnt1,ll[N],rr[N];
struct date{
int l,r,lx,rx,id;
}q[N];
bool Cmp(const date &a,const date &b){
if(pos[a.l]==pos[b.l]) return a.r<b.r;
else return pos[a.l]<pos[b.l];
}
char a[N],s[N];
void work2(){
rk=1;y[x[1].id]=rk;
for(RG int i=2;i<=len;i++){
if(x[i-1].fir!=x[i].fir||x[i-1].sec!=x[i].sec) rk++;
y[x[i].id]=rk;
}
}
void work(){
sort(x+1,x+1+len,cmp);work2();
for(RG int i=1;i<=len;i<<=1){
for(RG int j=1;j+i<=len;j++) x[j].id=j,x[j].fir=y[j],x[j].sec=y[j+i];
for(RG int j=len-i+1;j<=len;j++) x[j].id=j,x[j].fir=y[j],x[j].sec=0;
sort(x+1,x+1+len,cmp);work2();
if(rk==len) break;
}
for(RG int i=1;i<=len;i++) sa[y[i]]=i;
}
void get_height(){
int kk=0;for(int i=1;i<=len;i++) rnk[sa[i]]=i;
for(RG int i=1;i<=len;i++){
if(kk) kk--;
int j=sa[rnk[i]-1];
while(a[i+kk]==a[j+kk]) kk++;
height[rnk[i]]=kk;
}
}
void make_ST(){
pre[0]=1;for(RG int i=1;i<=20;i++) pre[i]=pre[i-1]<<1;
pre2[0]=-1;for(RG int i=1;i<=len;i++) pre2[i]=pre2[i>>1]+1;
for(RG int i=2;i<=len;i++) ST[i][0]=height[i];
for(RG int j=1;j<=20;j++)
for(RG int i=2;i<=len;i++){
if(i+pre[j]-1<=len){
ST[i][j]=min(ST[i][j-1],ST[i+pre[j-1]][j-1]);
}
}
}
int query(int l,int r){
if(l>r) swap(l,r);
int x=pre2[r-l+1];
return min(ST[l][x],ST[r-pre[x]+1][x]);
}
int LCP(RG int l,RG int r){
if(l==r) return len-sa[l];
if(l>r) swap(l,r);
return query(l+1,r);
}
int get_l(RG int x,RG int le){
int ret=x,l=1,r=x;
while(l<=r){
int mid=(l+r)>>1;
if(LCP(x,mid)>=le) ret=mid,r=mid-1;
else l=mid+1;
}
return ret;
}
int get_r(RG int x,RG int le){
RG int ret=x,l=x,r=len;
while(l<=r){
RG int mid=(l+r)>>1;
if(LCP(x,mid)>=le) ret=mid,l=mid+1;
else r=mid-1;
}
return ret;
}
void update(RG int x,RG int val){tong[x]+=val;}
int ask(RG int l,RG int r){
RG int ret=0;
if(bel[l]==bel[r]){
for(RG int i=l;i<=r;i++) if(tong[i]) ret++;
}
else{
for(RG int i=l;i<=rr[bel[l]];i++) if(tong[i]) ret++;
for(RG int i=ll[bel[r]];i<=r;i++) if(tong[i]) ret++;
for(RG int i=bel[l]+1;i<=bel[r]-1;i++) ret+=blockans[i];
}
return ret;
}
void Modui(){
block=sqrt(len);for(RG int i=1;i<=len;i++) pos[i]=(i-1)/block+1;
block2=sqrt(N-1);for(RG int i=1;i<=N-1;i++) bel[i]=(i-1)/block2+1;
if((N-1)%block2) cnt1=(N-1)/block2+1;
else cnt1=(N-1)/block2;
for(RG int i=1;i<=cnt1;i++) ll[i]=(i-1)*block2+1,rr[i]=i*block2;
sort(q+1,q+1+m,Cmp);
for(RG int l=1,r=0,i=1;i<=m;i++){
while(l>q[i].l){l--;update(g[l],1);if(tong[g[l]]==1)blockans[bel[g[l]]]++;}
while(r<q[i].r){r++;update(g[r],1);if(tong[g[r]]==1)blockans[bel[g[r]]]++;}
while(l<q[i].l){update(g[l],-1);if(tong[g[l]]==0)blockans[bel[g[l]]]--;l++;}
while(r>q[i].r){update(g[r],-1);if(tong[g[r]]==0)blockans[bel[g[r]]]--;r--;}
ans[q[i].id]=ask(q[i].lx,q[i].rx);
}
}
int main(){
freopen("substr.in","r",stdin);
freopen("substr.out","w",stdout);
scanf("%d%d",&n,&m);
for(RG int i=1;i<=n;i++){
scanf("%s",s+1);int le=strlen(s+1);
for(RG int j=1;j<=le;j++) a[++len]=s[j],fr[len]=i;
a[++len]='#',fr[len]=N-1;
}
for(RG int i=1;i<=m;i++){
scanf("%d%d",&L[i],&R[i]);scanf("%s",s+1);
int le=strlen(s+1);lo[i]=le;st[i]=len+1;
for(RG int j=1;j<=le;j++) a[++len]=s[j],fr[len]=i+n;
a[++len]='#',fr[len]=N-1;
}
for(RG int i=1;i<=len;i++) x[i].id=i,x[i].fir=x[i].sec=a[i]-'a'+1;
work();get_height();make_ST();
for(RG int i=1;i<=m;i++){
int l=get_l(rnk[st[i]],lo[i]),r=get_r(rnk[st[i]],lo[i]);
q[i].l=l,q[i].r=r,q[i].lx=L[i],q[i].rx=R[i],q[i].id=i;
}
for(RG int i=1;i<=len;i++) g[i]=fr[sa[i]];
Modui();for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
一道叉姐的AC自动机鬼题的更多相关文章
- HDU 2222 AC自动机模板题
题目: http://acm.hdu.edu.cn/showproblem.php?pid=2222 AC自动机模板题 我现在对AC自动机的理解还一般,就贴一下我参考学习的两篇博客的链接: http: ...
- HDU 3065 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3065 题目大意:多个模式串,范围是大写字母.匹配串的字符范围是(0~127).问匹配串中含有哪几种模 ...
- HDU 2896 (AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896 题目大意:多个模式串.多个匹配串.其中串的字符范围是(0~127).问匹配串中含有哪几个模式串 ...
- HDU 2222(AC自动机模板题)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2222 题目大意:多个模式串.问匹配串中含有多少个模式串.注意模式串有重复,所以要累计重复结果. 解题 ...
- HDU3695(AC自动机模板题)
题意:给你n个字符串,再给你一个大的字符串A,问你着n个字符串在正的A和反的A里出现多少个? 其实就是AC自动机模板题啊( ╯□╰ ) 正着query一次再反着query一次就好了 /* gyt Li ...
- hdu2222 KeyWords Search AC自动机入门题
/** 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:题意:给定N(N <= 10000)个长度不大于50的模式串,再给定一个长度为L ...
- HDu-2896 病毒侵袭,AC自动机模板题!
病毒侵袭 模板题,不多说了.. 题意:n个不同的字符串分别代表病毒特征,给出m次查询,每次一个字符串(网址),求这个字符串中有几个病毒特征,分别从大到小输出编号,最后输出所有的带病毒网址个数.格式请看 ...
- [Bzoj3940] [AC自动机,USACO 2015 February Gold] Censor [AC自动机模板题]
AC自动机模板题(膜jcvb代码) #include <iostream> #include <algorithm> #include <cstdio> #incl ...
- hdu 2222(AC自动机模版题)
Keywords Search Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others ...
随机推荐
- laravel查看执行sql的
加个监听就好了~~~~而且很简单 1.在routes.php(api.php\web.php)中添加如下语句 Event::listen('illuminate.query', function($s ...
- (ajax)——jquery用法
例子:/* ajax获得状态 */ 点击事件 $("#findBycname").click(function(){ var company = ...
- Unity3d_GUI_2__(能量条的学习)
这和上一篇有点跳跃,不过GUI有官方文档,而且也可以查看编辑器自带的脚本文档,多看看API,多操作操作,肯定能熟练的.所以这篇我就介绍下一点小技巧,大佬就略过这篇了,不适合大佬,会被你们教育的. 1. ...
- 【转】使用nvm快速搭建 Node.js 开发环境
原文链接:http://www.cnblogs.com/shuoer/p/7802891.html 快速搭建 Node.js 开发环境 如果你想长期做 node 开发, 或者想快速更新 node 版本 ...
- Ceph luminous 安装配置
Ceph luminous 安装配置 #环境centos7 , Ceph V12 openstack pike 与 ceph 集成 http://www.cnblogs.com/elvi/p/7897 ...
- Linux常用基础命令
一.系统目录结构 约定俗成: bin (binaries)存放二进制可执行文件 sbin (super user binaries)存放二进制可执行文件,只有root才能访问 etc (e ...
- 自己动手编写IOC框架(二)
万事开头难,上篇已经起了一个头,之后的事情相对就简单了.上次定义了框架所需的dtd也就是规定了xml中该怎么写,有哪些元素.并且我们也让dtd和xml绑定在了一起,使dtd对xml的格式进行校验,并且 ...
- 负载均衡之 nginx
什么是负载均衡负载均衡(Load Balance)是分布式系统架构设计中必须考虑的因素之一,它通常是指,将请求/数据[均匀]分摊到多个操作单元上执行,负载均衡的关键在于[均匀].在使用nginx负载均 ...
- javascript算法题判断输入年份是否是闰年
用户输入一个年份,判断这个年是否是闰年.判断闰年条件:① 非整百年数除以4,无余为闰,有余不闰:② 整百年数除以400,无余为闰,有余不闰.比如:2000年,整百数年,就要用②公式,除以400,无余数 ...
- QT之UDP通信
前言:前一篇讲了TCP通信,这篇来看看UDP通信. 这里说明一下,UDP通信中分为三种通信分别为单播.组播和广播,下面将一一为大家介绍. 同样的我们都需要在工程文件中添加network QT += c ...