bzoj2754 [SCOI2012]喵星球上的点名
2017-03-15 16:59
302 查看
脑残错误调了将近一小时……这人没救了
……
其实跟bzoj3881差不多,建出AC自动机之后跑树链的并即可。因为只要出现姓或名就算一次,因此要把两次匹配得到的所有点一起做树链的并。
/************************************************************** Problem: 2754 User: hzoier Language: C++ Result: Accepted Time:1048 ms Memory:24460 kb ****************************************************************/ #include<cstdio> #include<cstring> #include<stdint.h> #include<algorithm> #include<vector> #include<map> using namespace std; const int maxn=200010; int insert(const int*,int); void getfail(); void bfs(); int LCA(int,int); void match(const vector<int>&,int); bool cmp(int,int); map<int,int>ch[maxn]; int f[maxn],q[maxn],val[maxn],d[maxn],cnt=0; int dfn[maxn],size[maxn],son[maxn],top[maxn],sum[maxn]={0},a[maxn]; vector<int>str1[maxn],str2[maxn]; int n,m,s[maxn],len1[maxn],len2[maxn],iter[maxn],ans[maxn]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&len1[i]); for(int j=0;j<len1[i];j++)scanf("%d",&s[j]); str1[i]=vector<int>(s,s+len1[i]); scanf("%d",&len2[i]); for(int j=0;j<len2[i];j++)scanf("%d",&s[j]); str2[i]=vector<int>(s,s+len2[i]); } for(int i=1,len;i<=m;i++){ scanf("%d",&len); for(int j=0;j<len;j++)scanf("%d",&s[j]); iter[i]=insert(s,len); } getfail(); bfs(); for(int i=1;i<=n;i++){ a[0]=0; match(str1[i],len1[i]); match(str2[i],len2[i]); sort(a+1,a+a[0]+1,cmp); sum[a[1]]++; ans[i]+=val[a[1]]; for(int j=2,x;j<=a[0];j++){ sum[a[j]]++; ans[i]+=val[a[j]]; x=LCA(a[j],a[j-1]); sum[x]--; ans[i]-=val[x]; } } for(int i=cnt;i;i--)sum[f[q[i]]]+=sum[q[i]]; for(int i=1;i<=m;i++)printf("%d\n",sum[iter[i]]); for(int i=1;i<=n;i++){ if(i>1)printf(" "); printf("%d",ans[i]); } return 0; } int insert(const int *a,int n){ int x=0; for(int i=0;i<n;i++){ if(!ch[x].count(a[i]))ch[x][a[i]]=++cnt; x=ch[x][a[i]]; } val[x]++; return x; } void getfail(){ int x,head=1,tail=1; for(map<int,int>::iterator it=ch[x].begin();it!=ch[x].end();it++)q[tail++]=it->second; d[0]=1; while(head!=tail){ x=q[head++]; d[x]=d[f[x]]+1; val[x]+=val[f[x]]; for(map<int,int>::iterator it=ch[x].begin();it!=ch[x].end();it++){ int y=f[x]; while(y&&!ch[y].count(it->first))y=f[y]; f[it->second]=(ch[y].count(it->first)?ch[y][it->first]:0); q[tail++]=it->second; } } } void bfs(){ fill(son,son+cnt+1,cnt+1); for(int i=cnt,x;i;i--){ x=q[i]; dfn[x]=size[f[x]]; size[x]++; size[f[x]]+=size[x]; if(size[x]>size[son[f[x]]])son[f[x]]=x; } for(int i=1,x;i<=cnt;i++){ x=q[i]; dfn[x]+=dfn[f[x]]+1; if(x==son[f[x]])top[x]=top[f[x]]; else top[x]=x; } } int LCA(int x,int y){ while(top[x]!=top[y]){ if(d[top[x]]<d[top[y]])swap(x,y); x=f[top[x]]; } return d[x]<d[y]?x:y; } void match(const vector<int>&str,int n){ int x=0; for(int i=0;i<n;i++){ while(x&&!ch[x].count(str[i]))x=f[x]; if(ch[x].count(str[i]))x=ch[x][str[i]]; a[++a[0]]=x; } } bool cmp(int x,int y){return dfn[x]<dfn[y];}View Code
相关文章推荐
- 【bzoj2754】[SCOI2012]喵星球上的点名 AC自动机优化的暴力
- BZOJ 2754: [SCOI2012]喵星球上的点名
- 【bzoj2754】 SCOI2012—喵星球上的点名
- [bzoj2754] [SCOI2012]喵星球上的点名
- BZOJ_2754__[SCOI2012]_喵星球上的点名_(暴力+后缀数组)
- BZOJ 2754: [SCOI2012]喵星球上的点名
- BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]
- BZOJ 2754: [SCOI2012]喵星球上的点名
- bzoj2754 [SCOI2012]喵星球上的点名(后缀数组+暴力)
- bzoj2754【SCOI2012】喵星球上的点名
- bzoj 2754: [SCOI2012]喵星球上的点名
- BZOJ 2754: [SCOI2012]喵星球上的点名
- [省选前题目整理][BZOJ 2754][SCOI 2012]喵星球上的点名(后缀数组)
- BZOJ 2754: [SCOI2012]喵星球上的点名
- bzoj2754:[SCOI2012]喵星球上的点名(后缀自动机)
- bzoj 2754: [SCOI2012]喵星球上的点名【AC自动机】
- [BZOJ2754][SCOI2012]喵星球上的点名
- BZOJ 2754 [SCOI2012]喵星球上的点名
- BZOJ 2754: [SCOI2012]喵星球上的点名
- [BZOJ2754][SCOI2012]喵星球上的点名