BZOJ2754 SCOI2012喵星球上的点名
绝世好题。
正当我犹豫不决时,hzwer说:“MAP!!!”
没错这题大大的暴力,生猛的stl,贼基尔爽,,ԾㅂԾ,,
由于我们求点名在名字中的子串个数,所以将点名建AC自动机,记录节点属于哪次点名,每次带着这位同学的所有名字去里面扫,注意判重
复杂度20000*100000以及玄学的stl复杂度。
By:大奕哥
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 int ans1[N],ans2[N],fail[N],n,m,cnt; 5 map<int,int>t[N]; 6 vector<int>pos[N],a[N]; 7 queue<int>q; 8 void build(int id) 9 { 10 int x,k;scanf("%d",&x);int now=0; 11 for(int i=1;i<=x;++i) 12 { 13 scanf("%d",&k); 14 if(!t[now][k])t[now][k]=++cnt; 15 now=t[now][k]; 16 } 17 pos[now].push_back(id); 18 } 19 void getfail() 20 { 21 for(map<int,int>::iterator i=t[0].begin();i!=t[0].end();++i) 22 { 23 int u=i->second; 24 q.push(u); 25 fail[u]=0; 26 } 27 while(!q.empty()) 28 { 29 int x=q.front();q.pop(); 30 for(map<int,int>::iterator i=t[x].begin();i!=t[x].end();++i) 31 { 32 int c=i->first,u=i->second; 33 q.push(u); 34 int k=fail[x]; 35 while(k&&!t[k][c])k=fail[k]; 36 fail[u]=t[k][c]; 37 } 38 } 39 } 40 bool v[N],mark[N]; 41 vector<int>H,M; 42 void get(int x,int p) 43 { 44 for(int i=p;i;i=fail[i]) 45 { 46 if(v[i])return; 47 v[i]=1;H.push_back(i); 48 for(int j=0;j<pos[i].size();++j) 49 if(!mark[pos[i][j]]) 50 { 51 mark[pos[i][j]]=1; 52 ans1[pos[i][j]]++; 53 ans2[x]++; 54 M.push_back(pos[i][j]); 55 } 56 } 57 return; 58 } 59 void find(int x,vector<int>g) 60 { 61 int ans=0,now=0,l=g.size(); 62 for(int i=0;i<l;++i) 63 { 64 int c=g[i]; 65 while(now&&!t[now][c])now=fail[now]; 66 now=t[now][c]; 67 get(x,now); 68 } 69 for(int i=0;i<H.size();++i)v[H[i]]=0; 70 for(int i=0;i<M.size();++i)mark[M[i]]=0; 71 H.clear();M.clear(); 72 return; 73 } 74 int main() 75 { 76 scanf("%d%d",&n,&m);int x,k; 77 for(int i=1;i<=n;++i) 78 { 79 scanf("%d",&x); 80 for(int j=1;j<=x;++j) 81 scanf("%d",&k),a[i].push_back(k); 82 a[i].push_back(-1);//添加非法字符防止姓和名连在一起成一个子串 83 scanf("%d",&x); 84 for(int j=1;j<=x;++j) 85 scanf("%d",&k),a[i].push_back(k); 86 } 87 for(int i=1;i<=m;++i)build(i); 88 getfail(); 89 for(int i=1;i<=n;++i) 90 find(i,a[i]); 91 for(int i=1;i<=m;++i)printf("%d\n",ans1[i]); 92 for(int i=1;i<n;++i)printf("%d ",ans2[i]); 93 printf("%d",ans2[n]); 94 return 0; 95 }
生命中真正重要的不是你遭遇了什么,而是你记住了哪些事,又是如何铭记的。