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 }

原文地址:https://www.cnblogs.com/guapisolo/p/9697151.html

时间: 2024-10-09 17:00:23

bzoj 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)的相关文章

BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那

BZOJ 2754([SCOI2012]喵星球上的点名-后缀数组统计序列集合中子序列出现次数)

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 805  Solved: 380 [Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,

BZOJ 2754: [SCOI2012]喵星球上的点名

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1926  Solved: 850[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这

bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1359  Solved: 618[Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那

BZOJ 2754 SCOI2012 喵星球上的点名 fail树+set启发式合并

题目大意:给定n个目标串和m个模式串,问这m个模式串每个在多少个目标串中出现过,以及n个目标串每个以最多多少个模式串为子串 我错了--就算用fail树+set启发式合并也优化不到O(nlog^2n)--这题的数据范围相当无解啊 首先将所有名字和点名的字符串全都插进AC自动机 将每个点上开一个set记录这个点是哪些喵星人的名字的前缀 然后建立fail树 沿着fail树从下到上启发式合并 每合并完一个点 如果这个点是某次点名的字符串 那么这次点名点到的喵星人就是这个点的set中的所有元素 统计答案即

bzoj2754 [SCOI2012]喵星球上的点名 (后缀数组+树状数组)

2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 2745 Solved: 1190 [Submit][Status][Discuss] Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么

P2336 [SCOI2012]喵星球上的点名(后缀自动机+莫队)

P2336 [SCOI2012]喵星球上的点名 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<map> #define rint register int using namespace std; int read(){ char c=getchar();int x=0; while(

洛谷 P2336 [SCOI2012]喵星球上的点名

题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 N 个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M 个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到. 然而,由于喵星人的字码过于古怪,以至于不能用 ASCII 码来表示.为了方便描述,a180285 决定用数串来表示喵星人的名字. 现在你能帮助 a180285 统计每次点名的时候有多少喵星人答到,以及 M 次点名结

[BZOJ2754] [SCOI2012]喵星球上的点名解题报告|后缀数组

a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点名,每次读出一个串的时候,如果这个串是一个喵星人的姓或名的子串,那么这个喵星人就必须答到. 然而,由于喵星人的字码过于古怪,以至于不能用ASCII码来表示.为了方便描述,a180285决定用数串来表示喵星人的名字. 现在你能帮助a180285统计每次点名的时候有多少喵星人答到,以及M次点名结束后每个喵星人答到多少次吗?