bzoj 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)
Posted guapisolo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 ",t.ans[i]); 122 for(int i=1;i<=n*2;i+=2) 123 printf("%d ",qans[i]); 124 puts(""); 125 return 0; 126 }
以上是关于bzoj 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)
bzoj2754 [SCOI2012]喵星球上的点名 (后缀数组+树状数组)