POJ 2774 Long Long Message

题目大意:

求两个长度不超过100000的字符串的最长公共子串, 注意是子串而非子序列, 所以是连续的.

 

简要分析:

二分答案M, 设两个串分别为A和B, 从左到右枚举一遍A的长为M的子串, 算出哈希值丢到map里面, 再从左到右枚举一遍B的长为M的子串, 算出哈希再到map里面找. O(NlogN).

 

代码实现:

View Code
 1 #include <cstdio>
2 #include <cstdlib>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6
7 typedef unsigned long long hash_t;
8 const int MAX_N = 100000, SEED = 99991;
9 char a[MAX_N + 1], b[MAX_N + 1];
10 int lena, lenb;
11 hash_t mypow[MAX_N];
12
13 struct hash_map_t {
14 static const int MOD = 196613;
15 int cnt, begin[MOD], next[MAX_N];
16 hash_t end[MAX_N];
17 void clear() { cnt = 0, memset(begin, -1, sizeof(begin)); }
18 hash_map_t() { cnt = 0, memset(begin, -1, sizeof(begin)); }
19 void push(hash_t x) {
20 int s = x % MOD;
21 for (int now = begin[s]; now != -1; now = next[now])
22 if (end[now] == x) return;
23 next[cnt] = begin[s];
24 begin[s] = cnt;
25 end[cnt ++] = x;
26 }
27 bool ask(hash_t x) {
28 int s = x % MOD;
29 for (int now = begin[s]; now != -1; now = next[now])
30 if (end[now] == x) return 1;
31 return 0;
32 }
33 } hash;
34
35 bool check(int len) {
36 hash.clear();
37 hash_t t = 0ULL;
38 for (int i = 0; i < len; i ++) t = t * SEED + a[i];
39 hash.push(t);
40 for (int i = 1; i < lena - len + 1; i ++) {
41 t = (t - mypow[len - 1] * a[i - 1]) * SEED + a[i + len - 1];
42 hash.push(t);
43 }
44 t = 0ULL;
45 for (int i = 0; i < len; i ++) t = t * SEED + b[i];
46 if (hash.ask(t)) return 1;
47 for (int i = 1; i < lenb - len + 1; i ++) {
48 t = (t - mypow[len - 1] * b[i - 1]) * SEED + b[i + len - 1];
49 if (hash.ask(t)) return 1;
50 }
51 return 0;
52 }
53
54 int main() {
55 mypow[0] = 1ULL;
56 for (int i = 1; i < MAX_N; i ++) mypow[i] = mypow[i - 1] * SEED;
57 while (scanf("%s%s", a, b) != EOF) {
58 lena = strlen(a), lenb = strlen(b);
59 int lb = 0, rb = min(lena, lenb) + 1;
60 while (lb + 1 < rb) {
61 int mid = (lb + rb) >> 1;
62 if (check(mid)) lb = mid;
63 else rb = mid;
64 }
65 printf("%d\n", lb);
66 }
67 return 0;
68 }
posted @ 2012-03-09 22:35  zcwwzdjn  阅读(360)  评论(0编辑  收藏  举报