[bzoj2754] [SCOI2012]喵星球上的点名

  对于点名串建AC自动机。。数字太大所以写了棵treap>_<......

  然后每个人直接暴力在AC自动机上跑名字就行了。每次匹配到一个节点都要沿着fail链更新答案。

  大概显然这样会被随便卡。所以有个小优化就是,沿着fail跳的时候如果之前已经走过了就不要再走了。具体实现用int比bool好一些。(懒得初始化系列)

  一开始#2。。。然后写了个输出优化,再把不必要的一些东西改掉后就#1了2333

  [bzoj2754] [SCOI2012]喵星球上的点名_第1张图片

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cstdlib>
  5 using namespace std;
  6 const int maxn=100233;
  7 struct zs{
  8     int too,pre;
  9 };
 10 int lc[maxn],rc[maxn],rnd[maxn],num[maxn],pre[maxn],tot;//pre[i]节点i最近被谁钦点 
 11 int rt[maxn],s[maxn],fail[maxn],size[maxn];
 12 int dl[maxn],DL[maxn];
 13 int len[2][maxn];
 14 
 15 int namlast[maxn],namtot;zs name[maxn];
 16 int surlast[maxn],surtot;zs sure[maxn];
 17 int vislast[maxn],vistot;zs vise[maxn];//变量名正确读法>_<:vis_last,vis_tot,vis_e 
 18 int called[20023],call[maxn],endpos[50023];
 19 int i,j,n,m,k;
 20 
 21 
 22 inline void lturn(int &x,int R){
 23     rc[x]=lc[R],lc[R]=x,x=R;
 24 }
 25 inline void rturn(int &x,int L){
 26     lc[x]=rc[L],rc[L]=x,x=L;
 27 }
 28 inline void ins(int &x,int v){
 29     if(!x){x=++tot,rnd[x]=rand()+(x<<1),num[x]=v;return;}
 30     if(v<num[x]){
 31         ins(lc[x],v);
 32         if(rnd[lc[x]]<rnd[x])rturn(x,lc[x]);
 33     }else if(v>num[x]){
 34         ins(rc[x],v);
 35         if(rnd[rc[x]]<rnd[x])lturn(x,rc[x]);
 36     }else return;
 37 }
 38 void getch(int x,int v,int &son){
 39     while(x&&num[x]!=v) x=v<num[x]?lc[x]:rc[x];
 40     son=x;
 41 }
 42 inline void insert(int len,int id){
 43     register int i,now=0,tmp;
 44     for(i=1;i<=len;i++){
 45         getch(rt[now],s[i],tmp);
 46         if(tmp)now=tmp;
 47             else ins(rt[now],s[i]),now=tot;
 48     }
 49     size[endpos[id]=now]++;
 50 }
 51 inline void getfail(){
 52     register int i,now,tmp,l=0,r=1,L,R,NOW;dl[1]=0;
 53     while(l<r){
 54         now=dl[++l];
 55         if(rt[now])dl[++r]=rt[now];
 56         for(L=0,R=rt[now]!=0,DL[R]=rt[now];L<R;){
 57             NOW=DL[++L];
 58             if(!now)fail[NOW]=0;else{
 59                 i=fail[now],getch(rt[i],num[NOW],tmp);
 60                 while(i&&!tmp)i=fail[i],getch(rt[i],num[NOW],tmp);
 61                 fail[NOW]=tmp;
 62             }
 63             if(lc[NOW])DL[++R]=dl[++r]=lc[NOW];
 64             if(rc[NOW])DL[++R]=dl[++r]=rc[NOW];
 65         }
 66     }
 67 }
 68 
 69 
 70 int ra;char rx;
 71 inline int read(){
 72     rx=getchar(),ra=0;
 73     while(rx<'0'||rx>'9')rx=getchar();
 74     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
 75 }
 76 char ss[12];int llen;
 77 inline void outx(int x){
 78     if(!x){putchar('0');return;}
 79     while(x)ss[++llen]=x%10,x/=10;
 80     while(llen)putchar(ss[llen--]+48);
 81 }
 82 
 83 
 84 int main(){
 85     register int i,j,len,k,now,to;
 86     n=read(),m=read();
 87     for(i=1;i<=n;i++){
 88         int len=read();
 89         for(j=1;j<=len;j++)name[++namtot].too=read(),name[namtot].pre=namlast[i],namlast[i]=namtot;
 90         len=read();
 91         for(j=1;j<=len;j++)sure[++surtot].too=read(),sure[surtot].pre=surlast[i],surlast[i]=surtot;
 92     }
 93     for(i=1;i<=m;insert(j,i),i++)
 94         for(len=j=read();len;len--)s[len]=read();
 95     getfail();
 96     for(i=1;i<=n;i++){
 97         for(j=namlast[i],now=0;j;j=name[j].pre){
 98             for(getch(rt[now],name[j].too,to);now&&!to;now=fail[now],getch(rt[now],name[j].too,to));
 99             for(k=now=to;k&&pre[k]<i;pre[k]=i,k=fail[k])if(size[k])
100                 called[i]+=size[k],call[k]++;
101         }
102         
103         for(j=surlast[i],now=0;j;j=sure[j].pre){
104             for(getch(rt[now],sure[j].too,to);now&&!to;now=fail[now],getch(rt[now],sure[j].too,to));
105             for(k=now=to;k&&pre[k]<i;pre[k]=i,k=fail[k])if(size[k])
106                 called[i]+=size[k],call[k]++;
107         }
108     }
109     for(i=1;i<=m;i++)outx(call[endpos[i]]),putchar('\n');
110     for(i=1;i<=n;i++){
111         outx(called[i]);if(i<n)putchar(' ');
112     }
113     return 0;
114 }
View Code

  具体实现有点烦。。。主要是要把姓名存下来。。我个傻逼写了一坨链式前向星,然后直接把所有东西都反过来处理了TAT

  其实复杂度还是略玄学。。。理论上是可以被卡的?。。。但不是那(du)么(liu)好(lai)卡(le)吧= =

你可能感兴趣的:([bzoj2754] [SCOI2012]喵星球上的点名)