小菜鸡求此题SAM不用莫队做法

P2336 [SCOI2012] 喵星球上的点名

~~我告诉您您可以帮我调吗~~
by FZzzz @ 2020-07-27 19:52:56


就是,加分隔符插 SAM,然后把点名的串丢上去匹配,然后第一问就是子树数颜色,第二问就是问每个颜色被多少个区间包含了,吧/fad
by FZzzz @ 2020-07-27 19:54:00


@[FZzzz](/user/174045) 求讲清楚一点qaq
by huangzirui @ 2020-07-27 19:55:26


```cpp #include<bits/stdc++.h> using namespace std; const int N=2e5+5; struct suffix_automotion{ int maxlen[N],link[N],tot,last; map<int,int> tr[N]; void extend(int id){ int p=last,cur=last=++tot; maxlen[cur]=maxlen[p]+1; for(;p && !tr[p][id];p=link[p]) tr[p][id]=cur; if(!p) link[cur]=1; else{ int q=tr[p][id]; if(maxlen[p]+1==maxlen[q]) link[cur]=q; else{ int clone=++tot; maxlen[clone]=maxlen[p]+1; link[clone]=link[q]; tr[clone]=tr[q]; for(;p && tr[p][id]==q;p=link[p]) tr[p][id]=clone; link[cur]=link[q]=clone; } } } }sam; int sz[N],vis[N],a[N],ans[N],mark[N]; vector<int> fame[N],name[N]; void color(int u,int col){ while(u&&vis[u]!=col){ sz[u]++; vis[u]=col; u=sam.link[u]; } } void color2(int u,int col){ while(u&&vis[u]!=col){ ans[col]+=mark[u]; vis[u]=col; u=sam.link[u]; } } int main(){ int n,m,len,x; sam.tot=1; int cnt=0; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i){ sam.last=1; scanf("%d",&len); for(int j=1;j<=len;++j){ scanf("%d",&x); fame[i].push_back(x); sam.extend(x); a[++cnt]=sam.last; } sam.last=1; scanf("%d",&len); for(int j=1;j<=len;++j){ scanf("%d",&x); name[i].push_back(x); sam.extend(x); a[++cnt]=sam.last; } } cnt=0; for(int i=1;i<=n;++i){ for(int j=0;j<fame[i].size();++j) color(a[++cnt],i); for(int j=0;j<name[i].size();++j) color(a[++cnt],i); } int u=1,flag=1; while(m--){ scanf("%d",&len); u=1;flag=1; for(int i=1;i<=len;++i){ scanf("%d",&x); if(!sam.tr[u][x]) flag=0; else u=sam.tr[u][x]; } if(flag) mark[u]++,printf("%d\n",sz[u]); else puts("0"); } cnt=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;++i){ for(int j=0;j<fame[i].size();++j) color2(a[++cnt],i); for(int j=0;j<name[i].size();++j) color2(a[++cnt],i); } for(int i=1;i<=n;++i) printf("%d ",ans[i]); return 0; } ``` 直接扔代码,扔完就跑真刺激(
by wurzang @ 2020-07-27 19:58:30


@[FZzzz](/user/174045) 没看出来什么是 ”颜色“ 啊 QAQ
by huangzirui @ 2020-07-27 19:58:34


@[huangzirui](/user/35891) 啊,就是拍扁到 dfs 序上面变成区间数颜色,然后第一问就直接 HH 的项链那样做,第二问,如果一个区间是 $[l,r]$,扫描线扫到 $l$ 的时候给 $[l,n]$ 加上 $1$,扫到 $r+1$ 给 $[l,n]$ 减去 $1$,然后一个位置的贡献就是他的权值减去他祖先的权值吧/kk
by FZzzz @ 2020-07-27 20:00:10


第二问也可以线段树合并
by Niko! @ 2020-07-27 20:00:14


在线段树上打标记
by Niko! @ 2020-07-27 20:00:29


@[huangzirui](/user/35891) 就是,如果前缀节点的最后一个字符是属于第 $i$ 个人名的,那就把它染成第 $i$ 种颜色/kk
by FZzzz @ 2020-07-27 20:01:07


祖先-->前驱 不知道为啥打错了/kk
by FZzzz @ 2020-07-27 20:01:33


| 下一页