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


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

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

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

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

      

      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('
    ');
    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)吧= =

  • 相关阅读:
    linux下修改MAC地址方法
    自定义VBS脚本(统计在指定文件中搜索字符串出现的次数)
    mysql 1053错误,无法启动的解决方法
    VBS自编写脚本。(实现批量修改文件名且在执行前,备份原有文件夹中的文件)
    在命令提示符下,怎么查看windows开启了哪些服务?
    vbs 读取txt是读取特定的行
    Windows XP SP3中远程桌面实现多用户登陆
    Linux关机命令详解
    VBS 读取文本文件特殊字符前如逗号的值并赋值给变量
    VBS基础篇
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5194151.html
Copyright © 2020-2023  润新知