• 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
    ",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
  • 相关阅读:
    树的前序 中序 后序遍历
    算法入门经典-第四章 例题4-3 救济金发放
    算法入门经典-第五章 例题6-10 下落的树叶
    排序(三) 选择排序

    printf格式输出总结
    并查集
    异或的应用
    ActionContext详解
    ActionContext表格总结
  • 原文地址:https://www.cnblogs.com/hzoier/p/6555140.html
Copyright © 2020-2023  润新知