1. 程式人生 > >BZOJ2754 SCOI2012喵星球上的點名

BZOJ2754 SCOI2012喵星球上的點名

pop esp tor clu 喵星球上的點名 uil pos const ()

絕世好題。

正當我猶豫不決時,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 }

BZOJ2754 SCOI2012喵星球上的點名