【题解】Bovine Genomics G奶牛基因组(金)

查看原题请戳这里

首先,这道题让求最大值最小,于是我们就很自然得想到了去二分这个最小值。

那么,怎么check呢?

我们发现,如果直接暴力去check,即二分区间长度+暴力枚举字符串+暴力枚举区间左端点+暴力对比,那么时间复杂度是O(n2m2log2n)O(n^2m^2log_2n)的。(引人深思的复杂度……)

很显然,我们需要去优化这个时间复杂度。

首先,如果我们对要进行对比的区间进行哈希,然后用set进行判断,就可以将时间复杂度降低到O(nm2log22n)O(nm^2log_2^2n)

这里提供两种用set去检验的思路:

  1. 用一个set去记录好的基因有多少不同的哈希值cnt1cnt1,再用一个set去记录坏的基因有多少不同的哈希值cnt2cnt2,再用一个set去记录好的基因和坏的基因一共有多少不同的哈希值cnt3cnt3,如果cnt3cnt1=cnt2cnt3-cnt1=cnt2,那么好的基因的哈希值和坏的基因的哈希值没有重复。
  2. 用一个set去储存好的基因的哈希值,然后用set自带的find函数查询每一个坏的基因的哈希值是否在这个集合中出现过。

但是,即便如此,我们的时间复杂度依然无法通过这道题,主要原因是每次记录哈希值都占用了大量的时间。
hash[i]hash[j1]×priij+1(i>j)hash[i]-hash[j-1] imes pri^{i-j+1}(i>j)快速求得hash[i][j]hash[i][j]的值。

时间复杂度:O(nmlog2n)O(nmlog_2 n)

code:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
#define ll long long
#define INF 0x7fffffff
#define re register
#define rep(i,a,b) for(int i = (a); i <= (b); i++)
#define qwq printf("qwq
");
#define mod1 122420729
#define mod2 131937371

using namespace std;

int read()
{
	register int x = 0,f = 1;register char ch;
	ch = getchar();
	while(ch > '9' || ch < '0'){if(ch == '-') f = -f;ch = getchar();}
	while(ch <= '9' && ch >= '0'){x = x * 10 + ch - 48;ch = getchar();}
	return x * f;
}

int n,m,l,r,mid,cnt1,cnt2,cnt3;

long long hfg[505][505],hfb[505][505],a[505],b[505],c[505];

char good[505][505],bad[505][505];

void Hash()
{
	memset(hfg,0,sizeof(hfg));
	memset(hfb,0,sizeof(hfb));
	for(register int i = 0; i < n; i++) hfg[i][0] = good[i][0];
	for(register int i = 0; i < n; i++) hfb[i][0] = bad[i][0];
	for(register int i = 0; i < n; i++)
		for(register int j = 1; j < m; j++)
			hfg[i][j] = hfg[i][j - 1] * 13331 + good[i][j];
	for(register int i = 0; i < n; i++)
		for(register int j = 1; j < m; j++)
			hfb[i][j] = hfb[i][j - 1] * 13331 + bad[i][j];
}

void get_Hash(int s,int l)
{
	if(s == 0)
	{
		for(int i = 0; i < n; i++) a[i] = hfg[i][l - 1];
		for(int i = 0; i < n; i++) b[i] = hfb[i][l - 1];
		return ;
	}
	for(int i = 0; i < n; i++) a[i] = hfg[i][s + l - 1] - hfg[i][s - 1] * c[l];
	for(int i = 0; i < n; i++) b[i] = hfb[i][s + l - 1] - hfb[i][s - 1] * c[l];
}

set<int> se1,se2,se3;

bool check(int l)
{
	for(register int i = 0; i + l - 1 < m; i++)
	{
		get_Hash(i,l);
		int flag = 1;
		se1.clear(); se2.clear(); se3.clear();
		for(register int j = 0; j < n; j++) se1.insert(a[j]),se3.insert(a[j]);
		cnt1 = se1.size();
		for(register int j = 0; j < n; j++) se2.insert(b[j]),se3.insert(b[j]);
		cnt2 = se2.size();
		if(se3.size() - cnt1 == cnt2) return true;
	}
	return false;
}

int main()
{
	n = read(); m = read();
	c[1] = 13331;
	for(int i = 2; i <= m; i++) c[i] = c[i - 1] * 13331; 
	for(register int i = 0; i < n; i++) cin >> good[i];
	for(register int i = 0; i < n; i++) cin >> bad[i];
	l = 1; r = m;
	Hash();
	while(l < r)
	{
		mid = (l + r) >> 1;
		if(check(mid)) r = mid;
		else l = mid + 1;
	}
	
	get_Hash(1,4);
	printf("%d
",r);
    return 0;
}

原文地址:https://www.cnblogs.com/aurorapolaris/p/13449111.html