首页 > 代码库 > bzoj 3413: 匹配
bzoj 3413: 匹配
Description
Input
第一行包含一个整数n(≤100000)。
第二行是长度为n的由0到9组成的字符串。
第三行是一个整数m。
接下来m≤5·10^4行,第i行是一个由0到9组成的字符串s,保证单行字符串长度小于等于10^5,所有字符串长度和小于等于3·10^6
Output
输出m行,第i行表示第si和S匹配所比较的次数。
建出后缀树,将询问按第一次匹配到的位置从小到大排序,离线处理,用树状数组维护后缀树的dfs序
从左到右加入后缀,加入时将后缀树上对应点+1,处理第一次匹配位置在这个后缀的询问
对每个询问串,在后缀树上匹配一次,查询经过的每个点的子树和
#include<bits/stdc++.h>typedef long long i64;const int N=2e5+77;int n,m;char s1[N];int nx[N][10],ch[N][10],l[N],fa[N],pv=1,ptr=1,lr[N][2],in[N],q[N],ql,qr,id[N][2],idp=0;int bit[N],bs[N],ws[N];void inc(int w){ for(++bs[w];w<=idp;w+=w&-w)++bit[w];}bool _=0;int sum(int w){ if(_)return bs[w]; int s=0; for(;w;w-=w&-w)s+=bit[w]; return s;}void ins(int pos){ int x=s1[pos]-=‘0‘; int p=pv,np=++ptr; l[np]=l[p]+1; while(p&&!nx[p][x])nx[p][x]=np,p=fa[p]; if(!p)fa[np]=1; else{ int q=nx[p][x]; if(l[q]==l[p]+1)fa[np]=q; else{ int nq=++ptr; lr[nq][1]=n+1; l[nq]=l[p]+1; memcpy(nx[nq],nx[q],sizeof(nx[0])); fa[nq]=fa[q]; fa[q]=fa[np]=nq; while(p&&nx[p][x]==q)nx[p][x]=nq,p=fa[p]; } } ws[pos]=np; lr[np][1]=n; pv=np;}void dfs(int w){ id[w][0]=++idp; for(int i=0;i<10;++i)if(ch[w][i])dfs(ch[w][i]); id[w][1]=idp;}void mins(int&a,int b){if(a>b)a=b;}i64 as[50007];struct Q{ char*s; int len,e,ID; void match(){ int w=1,p=0; for(int i=0;i<len&&w;++i){ int x=s[i]-‘0‘; if(p==lr[w][1])p=lr[w=ch[w][x]][0]; else if(s1[++p]!=x)w=0; } e=w?p-len+1:n+1; } void cal(){ int w=1,p=0; for(int i=0;i<len&&w;++i){ int x=s[i]-‘0‘; if(p==lr[w][1])p=lr[w=ch[w][x]][0]; else if(s1[++p]!=x)w=0; as[ID]+=sum(id[w][1])-sum(id[w][0]-1); } as[ID]+=e>n?n:e-1; } bool operator<(Q x)const{return e<x.e;}}qs[50007];char s2[5000007],*sp2=s2;int main(){ scanf("%d%s",&n,s1+1); for(int i=n;i;--i)ins(i); for(int i=1;i<=ptr;++i)++in[fa[i]]; for(int i=1;i<=ptr;++i)if(!in[i])q[++qr]=i; in[1]=-1; while(ql!=qr){ int w=q[++ql],f=fa[w]; if(!--in[f])q[++qr]=f; lr[w][0]=lr[w][1]-l[w]+l[f]+1; mins(lr[f][1],lr[w][0]-1); ch[f][s1[lr[w][0]]]=w; } dfs(1); scanf("%d",&m); for(int i=0;i<m;++i){ scanf("%s",sp2); qs[i].s=sp2; qs[i].len=strlen(sp2); qs[i].match(); qs[i].ID=i; sp2+=qs[i].len+2; } std::sort(qs,qs+m); int qp=0; for(int i=1;i<=n;++i){ inc(id[ws[i]][0]); for(;qp<m&&qs[qp].e==i;++qp)qs[qp].cal(); } _=1; for(int i=1;i<=idp;++i)bs[i]+=bs[i-1]; for(;qp<m;++qp)qs[qp].cal(); for(int i=0;i<m;++i)printf("%lld\n",as[i]); return 0;}
bzoj 3413: 匹配
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。