[BZOJ4779] [Usaco2017 Open]Bovine Genomics(hash + 二分)

传送门

网上的题解:

枚举左端点,二分右端点位置,最后所有左端点的答案取最小值

我的题解。。。

二分答案,枚举左端点,看看是否有解。。

好像和上面是反的,但是思路没问题

过程用hash判重

#include <cstdio>
#include <cstring>
#define N 1001
#define p 100007
#define ULL unsigned long long

int n, m, cnt, ans;
char s[N];
ULL sum[N][N], bit[N], to[p];
int head[p], next[p];

inline void insert(ULL v)
{
	int i, u = v % p;
	for(i = head[u]; ~i; i = next[i])
		if(to[i] == v)
			return;
	to[cnt] = v;
	next[cnt] = head[u];
	head[u] = cnt++;
}

inline bool find(ULL v)
{
	int i, u = v % p;
	for(i = head[u]; ~i; i = next[i])
		if(to[i] == v)
			return 1;
	return 0;
}

inline bool check(int x)
{
	int i, j, f;
	for(j = x; j <= m; j++)
	{
		f = 0;
		cnt = 0;
		memset(head, -1, sizeof(head));
		for(i = 1; i <= n * 2; i++)
			if(i <= n)
				insert(sum[i][j] - sum[i][j - x] * bit[x]);
			else if(find(sum[i][j] - sum[i][j - x] * bit[x]))
			{
				f = 1;
				break;
			}
		if(!f) return 1;
	}
	return 0;
}

int main()
{
	int i, j, x, y, mid;
	scanf("%d %d", &n, &m);
	bit[0] = 1;
	for(i = 1; i <= m; i++) bit[i] = bit[i - 1] * 107;
	for(i = 1; i <= n * 2; i++)
	{
		scanf("%s", s + 1);
		for(j = 1; j <= m; j++)
			sum[i][j] = sum[i][j - 1] * 107 + s[j];
	}
	x = 1;
	y = m;
	while(x <= y)
	{
		mid = (x + y) >> 1;
		if(check(mid)) ans = mid, y = mid - 1;
		else x = mid + 1;
	}
	printf("%d
", ans);
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhenghaotian/p/7567098.html