bzoj3820 虫逢

Description

小强和阿米巴是好朋友。
阿米巴告诉小强,变形虫(又叫阿米巴虫)和绝大多数生物一样,也是有 DNA 的。并且,变形虫可以通过分裂的方式进行无性繁殖。
我们把一个变形虫的基因组抽象成一个大小为 L 的基因集合。每个基因都是一个 4 位长的字符串(字符包括大小写字母、数字、符号“~!@#$%^&()[]`:;"'<>,.?/|\=-{}”)。现在,有 N 个变形虫凑到了一起。由于他们是从天南海北过来的,我们可以认为,他们的基因组都是从一个大小为 M 的“变形虫基因库“中独立的随机的选取L个基因得到的。目前人类并不了解这个基因库里都有什么基因,但是我们知道它的大小是 M。
这时,环境突然发生巨变。这 N 个变形虫在外界的刺激下同时进行了一次分裂。每个变形虫分裂成了两个。分裂的过程中,原来的变形虫的基因组(基因的集合)被原样的复制成了两份,分别进入两个新的变形虫。两个新变形虫中的一只的基因组中有一半发生了突变,被替换为“变形虫基因库”中随机的其他的基因。如果两个变形虫是由原来的一个变形虫产生的,我们叫它们“同源”的。
给出 2N 个变形虫的基因组,请你找出每个变形虫同源的另一只虫是谁。

Input

第一行三个整数 N、M、L。
接下来一行 2NL×4个字符,依次表示每个集合中的元素。集合内的元素之间的顺序是无关紧要的。

Output

输出 2N 行,每行一个整数表示第 i 个变形虫(从 1 开始标号)同源的另一只变形虫是谁。

Sample Input

2 100 6
H[P,86(^,<n&7x_sg"ly67m2h$n+5'!vhp5ia.@gm:4-njsqsig!h[p,7x_s86(^>aNQ22'B5'!V<fd!f!6xnjsq>!]dHp5I

Sample Output

3
4
1
2

explanation
输入文件一共有两行。四个基因组分别是
“H[P,”,“86(^”,“,<n&”,“7x_s”,“g"ly”, “67m2”<br="">
“H$n+”,“5'!V”,“Hp5I”,“A.@G”,“M:4-”,“NJsq”
“siG!”,“H[P,”,“7X_S”,“86(^”,“>aNQ”,“22'B”
“5'!V”,“<fd!”,“f!6x”,“njsq”,“>!]d”,“Hp5I”
明显,1、3是同源的,2、4是同源的。

HINT 

一共有 10 个测试点。数据均为按照题目中描述的方法随机生成的。对于非同源的两个变形虫,他们的基因组的交的大小均小于 L/2。对于同源的两个变形虫,他们的基因组的交的大小刚好是 L/2
最大的一个测试数据的大小是 17MB 左右(2NL×4=17576000)。在测评系统上,由于磁盘缓存的存在,使用 scanf 将数据读入需要的时间小于 0.1 秒。请不要使用 cin。
N<=16900,M<=16900,L<=130
 
正解:$hash$+随机化。
先把每个串取两个$hash$,每次重新取两个$hash$。
对于一个变形虫,我们把它的两个$hash$的最小值分别取出来。
我们计算一下同源变形虫$hash$相等的概率,如果只有一个$hash$,那么概率是$\frac{1}{3}$,有两个$hash$就是$\frac{1}{9}$。
不同源变形虫$hash$的概率,一个$hash$是$\frac{1}{l}$,两个$hash$是$\frac{1}{l^{2}}$,即$\frac{1}{n}$。
于是我们可以每次给一个串随机一个$hash$值,然后做匹配即可,期望$9$次就能匹配完。
 
 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define rhl (2573287)
 6 #define M (5000010)
 7 #define N (40010)
 8 
 9 using namespace std;
10 
11 struct edge{ int nt,to; }g[M];
12 struct data{ int x,y,z; }q[N];
13 
14 int a[N][135],mt[N],q1[M],q2[M],vis[M],head[rhl],n,m,l,num,cnt,res,flg;
15 char ch;
16 
17 il int cmp(const data &a,const data &b){
18   if (a.x==b.x) return a.y<b.y; return a.x<b.x;
19 }
20 
21 il int insert(RG int to){
22   RG int from=to%rhl;
23   for (RG int i=head[from];i;i=g[i].nt) if (g[i].to==to) return i;
24   g[++num]=(edge){head[from],to},head[from]=num; return num;
25 }
26 
27 il int eql(RG int x,RG int y){
28   ++flg; RG int mch=0;
29   for (RG int i=1;i<=l;++i) vis[a[x][i]]=flg;
30   for (RG int i=1;i<=l;++i) mch+=vis[a[y][i]]==flg;
31   return mch==(l>>1);
32 }
33 
34 il int solve(){
35   random_shuffle(q1+1,q1+num+1),random_shuffle(q2+1,q2+num+1),cnt=0; RG int mch=0;
36   for (RG int i=1;i<=n;++i){
37     if (mt[i]) continue; ++cnt,q[cnt].x=q1[a[i][1]],q[cnt].y=q2[a[i][1]],q[cnt].z=i;
38     for (RG int j=2;j<=l;++j) q[cnt].x=min(q[cnt].x,q1[a[i][j]]),q[cnt].y=min(q[cnt].y,q2[a[i][j]]);
39   }
40   sort(q+1,q+cnt+1,cmp);
41   for (RG int i=1,j;i<cnt;++i){
42     if (mt[q[i].z]) continue;
43     for (j=i;j<cnt && q[j+1].x==q[j].x && q[j+1].y==q[j].y;++j);
44     for (RG int u=i;u<j;++u){
45       if (mt[q[u].z]) continue;
46       for (RG int v=u+1;v<=j;++v)
47     if (!mt[q[v].z] && eql(q[u].z,q[v].z)){
48       mt[q[u].z]=q[v].z,mt[q[v].z]=q[u].z,++mch; break;
49     }
50     }
51   }
52   return mch;
53 }
54 
55 int main(){
56 #ifndef ONLINE_JUDGE
57   freopen("pairing.in","r",stdin);
58   freopen("pairing.out","w",stdout);
59 #endif
60   srand(19260817),cin>>n>>m>>l,n<<=1; while (ch<'!') ch=getchar();
61   for (RG int i=1;i<=n;++i)
62     for (RG int j=1,x=0;j<=l;++j,x=0){
63       for (RG int k=1;k<=4;++k,ch=getchar()) x=(x<<7)+(int)ch;
64       a[i][j]=insert(x);
65     }
66   for (RG int i=1;i<=num;++i) q1[i]=q2[i]=i;
67   res=n>>1; while (res) res-=solve();
68   for (RG int i=1;i<=n;++i) printf("%d\n",mt[i]); return 0;
69 }

 

posted @ 2017-09-29 19:13  wfj_2048  阅读(313)  评论(0编辑  收藏  举报