Description
小强和阿米巴是好朋友。
阿米巴告诉小强,变形虫(又叫阿米巴虫)和绝大多数生物一样,也是有 DNA 的。并且,变形虫可以通过分裂的方式进行无性繁殖。
我们把一个变形虫的基因组抽象成一个大小为 L 的基因集合。每个基因都是一个 4 位长的字符串(字符包括大小写字母、数字、符号“[email protected]#$%^&()[]`:;"‘<>,.?/|\=-{}”)。现在,有 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‘[email protected]: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”,“[email protected]”,“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 }