BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)

题目大意:略

由于字符集大,要用map维护Trie树

并不能用AC自动机的Trie图优化,不然内存会炸

所以我用AC自动机暴跳fail水过的

显然根据喵星人建AC自动机是不行的,所以要根据问题建

然而这题有一些很艮的地方:

1.如果一个喵的名和姓都被点到,那他只被点到了一次

2.询问的串可能相同

3.如果map中并不包含某个元素,但你强行用数组表示它,那么它会返回0,然后这个元素会被强行插入map并赋值成0

  1 #include <map>
  2 #include <queue>
  3 #include <vector>
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <algorithm>
  7 #define ll long long 
  8 #define ui unsigned int
  9 #define inf 0x3f3f3f3f
 10 #define N 100010
 11 #define imap map<int,int>::iterator
 12 using namespace std;
 13 //re
 14 int n,m;
 15 int a[N],len[N],l[N],r[N],qans[N],use[N],b[N];
 16 int gint()
 17 {
 18     int rett=0,fh=1;char c=getchar();
 19     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
 20     while(c>='0'&&c<='9'){rett=(rett<<3)+(rett<<1)+c-'0';c=getchar();}
 21     return rett*fh;
 22 }
 23 struct Trie
 24 {
 25     map<int,int>ch[N];
 26     vector<int>ed[N];
 27     int val[N],fail[N],ans[N],tot;
 28     void build_trie(int j)
 29     {
 30         int x=0;
 31         for(int i=1;i<=len[j];i++){
 32             imap k=ch[x].find(a[i]);
 33             if(k==ch[x].end())
 34                 ch[x][a[i]]=++tot,val[tot]=a[i],x=tot;
 35             else x=(*k).second;
 36             if(i==len[j]) ed[x].push_back(j);
 37         }
 38     }
 39     void Build()
 40     {
 41         for(int i=1;i<=m;i++){
 42             len[i]=gint();
 43             for(int j=1;j<=len[i];j++)
 44                 a[j]=gint();
 45             build_trie(i);
 46         }
 47     }
 48     void Fail()
 49     {
 50         queue<int>q;
 51         int x=0,i,j,y,z;
 52         for(imap k=ch[0].begin();k!=ch[0].end();k++)
 53             q.push((*k).second);
 54         while(!q.empty())
 55         {
 56             x=q.front();q.pop();
 57             for(imap k=ch[x].begin();k!=ch[x].end();k++)
 58             {
 59                 i=(*k).first;
 60                 j=(*k).second;
 61                 y=fail[x];
 62                 while(!ch[y][i]&&y) 
 63                     y=fail[y];
 64                 fail[j]=ch[y][i];
 65                 q.push(j);
 66             }
 67         }
 68     }
 69     void query(int p)
 70     {
 71         int x=0;
 72         queue<int>q;
 73         for(int i=l[p];i<=r[p];i++)
 74         {
 75             while(!ch[x][b[i]]&&x)
 76                 x=fail[x];
 77             x=ch[x][b[i]];
 78             for(int j=x;j;j=fail[j])
 79                 if(ed[j].size()>0&&!use[j]){ 
 80                     for(int k=0;k<ed[j].size();k++)
 81                         ans[ed[j][k]]++,qans[p]++;
 82                     use[j]=1,q.push(j);
 83                 }
 84         }
 85         x=0;
 86         for(int i=l[p+1];i<=r[p+1];i++)
 87         {
 88             while(!ch[x][b[i]]&&x)
 89                 x=fail[x];
 90             x=ch[x][b[i]];
 91             for(int j=x;j;j=fail[j])
 92                 if(ed[j].size()>0&&!use[j]){ 
 93                     for(int k=0;k<ed[j].size();k++)
 94                         ans[ed[j][k]]++,qans[p]++;
 95                     use[j]=1,q.push(j);
 96                 }
 97         }
 98         while(!q.empty())
 99             {int x=q.front();q.pop();use[x]=0;}
100     }
101 }t;
102 
103 int main()
104 {
105     //freopen("name1.in","r",stdin);
106     scanf("%d%d",&n,&m);
107     int cnt=1;
108     for(int i=1;i<=n*2;i++){
109         l[i]=cnt;
110         int num=gint();
111         r[i]=l[i]+num-1;
112         for(int j=l[i];j<=r[i];j++)
113             b[j]=gint();
114         cnt=r[i]+1;
115     }
116     t.Build();
117     t.Fail();
118     for(int i=1;i<=n*2;i+=2)
119         t.query(i);
120     for(int i=1;i<=m;i++)
121         printf("%d\n",t.ans[i]);
122     for(int i=1;i<=n*2;i+=2)
123         printf("%d ",qans[i]);
124     puts("");
125     return 0;
126 }

 

posted @ 2018-09-24 22:49  guapisolo  阅读(174)  评论(0编辑  收藏  举报