[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; }