bzoj2754 [SCOI2012]喵星球上的点名

传送门

脑残错误调了将近一小时……这人没救了

……

其实跟bzoj3881差不多,建出AC自动机之后跑树链的并即可。因为只要出现姓或名就算一次,因此要把两次匹配得到的所有点一起做树链的并。

  1 /**************************************************************
  2     Problem: 2754
  3     User: hzoier
  4     Language: C++
  5     Result: Accepted
  6     Time:1048 ms
  7     Memory:24460 kb
  8 ****************************************************************/
  9 #include<cstdio>
 10 #include<cstring>
 11 #include<stdint.h>
 12 #include<algorithm>
 13 #include<vector>
 14 #include<map>
 15 using namespace std;
 16 const int maxn=200010;
 17 int insert(const int*,int);
 18 void getfail();
 19 void bfs();
 20 int LCA(int,int);
 21 void match(const vector<int>&,int);
 22 bool cmp(int,int);
 23 map<int,int>ch[maxn];
 24 int f[maxn],q[maxn],val[maxn],d[maxn],cnt=0;
 25 int dfn[maxn],size[maxn],son[maxn],top[maxn],sum[maxn]={0},a[maxn];
 26 vector<int>str1[maxn],str2[maxn];
 27 int n,m,s[maxn],len1[maxn],len2[maxn],iter[maxn],ans[maxn];
 28 int main(){
 29     scanf("%d%d",&n,&m);
 30     for(int i=1;i<=n;i++){
 31         scanf("%d",&len1[i]);
 32         for(int j=0;j<len1[i];j++)scanf("%d",&s[j]);
 33         str1[i]=vector<int>(s,s+len1[i]);
 34         scanf("%d",&len2[i]);
 35         for(int j=0;j<len2[i];j++)scanf("%d",&s[j]);
 36         str2[i]=vector<int>(s,s+len2[i]);
 37     }
 38     for(int i=1,len;i<=m;i++){
 39         scanf("%d",&len);
 40         for(int j=0;j<len;j++)scanf("%d",&s[j]);
 41         iter[i]=insert(s,len);
 42     }
 43     getfail();
 44     bfs();
 45     for(int i=1;i<=n;i++){
 46         a[0]=0;
 47         match(str1[i],len1[i]);
 48         match(str2[i],len2[i]);
 49         sort(a+1,a+a[0]+1,cmp);
 50         sum[a[1]]++;
 51         ans[i]+=val[a[1]];
 52         for(int j=2,x;j<=a[0];j++){
 53             sum[a[j]]++;
 54             ans[i]+=val[a[j]];
 55             x=LCA(a[j],a[j-1]);
 56             sum[x]--;
 57             ans[i]-=val[x];
 58         }
 59     }
 60     for(int i=cnt;i;i--)sum[f[q[i]]]+=sum[q[i]];
 61     for(int i=1;i<=m;i++)printf("%d\n",sum[iter[i]]);
 62     for(int i=1;i<=n;i++){
 63         if(i>1)printf(" ");
 64         printf("%d",ans[i]);
 65     }
 66     return 0;
 67 }
 68 int insert(const int *a,int n){
 69     int x=0;
 70     for(int i=0;i<n;i++){
 71         if(!ch[x].count(a[i]))ch[x][a[i]]=++cnt;
 72         x=ch[x][a[i]];
 73     }
 74     val[x]++;
 75     return x;
 76 }
 77 void getfail(){
 78     int x,head=1,tail=1;
 79     for(map<int,int>::iterator it=ch[x].begin();it!=ch[x].end();it++)q[tail++]=it->second;
 80     d[0]=1;
 81     while(head!=tail){
 82         x=q[head++];
 83         d[x]=d[f[x]]+1;
 84         val[x]+=val[f[x]];
 85         for(map<int,int>::iterator it=ch[x].begin();it!=ch[x].end();it++){
 86             int y=f[x];
 87             while(y&&!ch[y].count(it->first))y=f[y];
 88             f[it->second]=(ch[y].count(it->first)?ch[y][it->first]:0);
 89             q[tail++]=it->second;
 90         }
 91     }
 92 }
 93 void bfs(){
 94     fill(son,son+cnt+1,cnt+1);
 95     for(int i=cnt,x;i;i--){
 96         x=q[i];
 97         dfn[x]=size[f[x]];
 98         size[x]++;
 99         size[f[x]]+=size[x];
100         if(size[x]>size[son[f[x]]])son[f[x]]=x;
101     }
102     for(int i=1,x;i<=cnt;i++){
103         x=q[i];
104         dfn[x]+=dfn[f[x]]+1;
105         if(x==son[f[x]])top[x]=top[f[x]];
106         else top[x]=x;
107     }
108 }
109 int LCA(int x,int y){
110     while(top[x]!=top[y]){
111         if(d[top[x]]<d[top[y]])swap(x,y);
112         x=f[top[x]];
113     }
114     return d[x]<d[y]?x:y;
115 }
116 void match(const vector<int>&str,int n){
117     int x=0;
118     for(int i=0;i<n;i++){
119         while(x&&!ch[x].count(str[i]))x=f[x];
120         if(ch[x].count(str[i]))x=ch[x][str[i]];
121         a[++a[0]]=x;
122     }
123 }
124 bool cmp(int x,int y){return dfn[x]<dfn[y];}
View Code

 

posted @ 2017-03-15 16:59  AntiLeaf  阅读(172)  评论(0编辑  收藏  举报