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

时间:2023-03-09 16:37:53
[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\n", ans);
return 0;
}