-
- 1.首先可以被很多暴力给搞过去;我以前也是这样水过去的
-
2.ac自动机
- 2.1
- 抽离fail树
- 对点名建自动机,建$fail$树的时候只保留询问节点;
- 对于一个喵,子串==在自动机里匹配到的所有节点的$fail$祖先并
- 把姓和名都放到里面去跑,得到所有的点,需要把这些点在新的$fail$树里的祖先全部标记
- 具体按照dfs序排序,每个点$q[i]$的贡献就是$lca(q[i-1],q[i])$到$q[i]$那段
- 统计第一问用树上差分$q[i]$处$++$,$lca(q[i-1],q[i])$处$--$,具体第二问直接记录每个点到根有多少次点名统计直接相减;
- $O(N \ log N)$
-
AC
1 #include<bits/stdc++.h> 2 #define rg register 3 #define il inline 4 #define Run(i,l,r) for(rg int i=l;i<=r;i++) 5 #define Don(i,l,r) for(rg int i=l;i>=r;i--) 6 using namespace std; 7 const int N=200010; 8 int n,m,o=1,hd[N],a[N],b[N],s[N],tot,fl[N],fa[N],st[N],ed[N],idx; 9 int val[N],vis[N],que[N],head,tail,sz,cnt,size[N],tp[N],dep[N],pos[N],ans[N],deep[N]; 10 il bool cmp(const int&x,const int&y){return st[x]<st[y];} 11 map<int,int>ch[N]; 12 map<int,int>::iterator it; 13 struct Edge{int v,nt;}E[N]; 14 il void adde(int u,int v){E[o]=(Edge){v,hd[u]};hd[u]=o++;} 15 il char gc(){ 16 static char*p1,*p2,s[1000000]; 17 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 18 return(p1==p2)?EOF:*p1++; 19 } 20 il int rd(){ 21 int x=0,f=1; char c=gc(); 22 while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();} 23 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); 24 return x*f; 25 } 26 void get_fl(){ 27 for(it=ch[0].begin();it!=ch[0].end();it++){ 28 int v=it->second; 29 que[++tail]=v; 30 if(vis[v])adde(fa[v],v),size[v]=1; 31 } 32 while(head < tail){ 33 int u=que[++head]; 34 for(it = ch[u].begin();it!=ch[u].end();it++){ 35 int v = it->second, c = it->first, w=fl[u]; 36 while(w&&!ch[w].count(c))w=fl[w]; 37 if(!ch[w].count(c))fl[v]=0; 38 else fl[v]=ch[w][c]; 39 if(vis[fl[v]])fa[v]=fl[v]; 40 else fa[v]=fa[fl[v]]; 41 que[++tail]=v; 42 if(vis[v])adde(fa[v],v),size[v]=1; 43 } 44 } 45 Don(i,tail,1)size[fa[que[i]]]+=size[que[i]]; 46 } 47 void dfs(int u,int T){ 48 int son=0; 49 st[u]=++idx;tp[u]=T; 50 dep[u]=dep[fa[u]]+1; 51 deep[u]=deep[fa[u]]+vis[u]; 52 for(int i=hd[u];i;i=E[i].nt){ 53 int v=E[i].v; 54 if(!son||size[v]>size[son])son=v; 55 } 56 if(son)dfs(son,T); 57 for(int i=hd[u];i;i=E[i].nt){ 58 int v=E[i].v; 59 if(son!=v)dfs(v,v); 60 } 61 ed[u]=idx; 62 } 63 il int lca(int x,int y){ 64 int tx=tp[x],ty=tp[y]; 65 while(tx!=ty){ 66 if(dep[tx]<dep[ty])y=fa[ty],ty=tp[y]; 67 else x=fa[tx],tx=tp[x]; 68 } 69 return dep[x]<dep[y]?x:y; 70 } 71 void find(int len){ 72 int x = 0 , c; 73 Run(i,1,len){ 74 c = s[tot+i]; 75 while(x&&!ch[x].count(c))x=fl[x]; 76 if(!ch[x].count(c))x=0; 77 else x=ch[x][c]; 78 if(vis[x])que[++tail]=x; 79 else if(fa[x])que[++tail]=fa[x]; 80 } 81 tot+=len; 82 } 83 void dfs(int u){ 84 for(int i=hd[u];i;i=E[i].nt) 85 dfs(E[i].v),val[u]+=val[E[i].v]; 86 } 87 int main(){ 88 freopen("bzoj2754.in","r",stdin); 89 freopen("bzoj2754.out","w",stdout); 90 n=rd(); m=rd(); 91 Run(i,1,n){ 92 a[i]=rd();Run(j,1,a[i])s[++tot]=rd(); 93 b[i]=rd();Run(j,1,b[i])s[++tot]=rd(); 94 } 95 Run(i,1,m){ 96 int x=rd(),u=0,y; 97 Run(j,1,x){ 98 if(!ch[u][y=rd()])ch[u][y]=++sz; 99 u=ch[u][y]; 100 } 101 vis[pos[i]=u]++; 102 } 103 get_fl(); 104 dfs(0,0); 105 tot=0; 106 Run(i,1,n){ 107 tail=0; 108 find(a[i]),find(b[i]); 109 if(!tail)continue; 110 sort(que+1,que+tail+1,cmp); 111 head=0; 112 Run(j,1,tail){ 113 if(!head||ed[que[j]]>ed[que[head]])head++; 114 que[head]=que[j]; 115 } 116 tail=head; 117 val[0]--,val[que[1]]++; 118 ans[i]+=deep[que[1]]; 119 Run(j,2,tail){ 120 int tmp = lca(que[j-1],que[j]); 121 val[tmp]--,val[que[j]]++; 122 ans[i] += deep[que[j]] - deep[tmp]; 123 } 124 } 125 dfs(0); 126 Run(i,1,m)printf("%d\n",val[pos[i]]); 127 Run(i,1,n)printf("%d ",ans[i]); 128 return 0; 129 }
相关文章: