[POJ3294]Life Forms(后缀数组)
Posted 蒟蒻zht的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POJ3294]Life Forms(后缀数组)相关的知识,希望对你有一定的参考价值。
统计大于一半的串中都出现过的子串,有多个按照字典序输出
二分子串长度 k,用 k 将height 数组分组,接下来直接判断就 ok。
有个小细节,平常统计所有串中都出现的最长子串时,把所有子串拼接起来的符号可以是相同的,但是这个题不行。(为什么?好好想想)
——代码
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define N 101001 5 6 int len, n, m, max_num, max_len; 7 int buc[N], x[N], y[N], sa[N], rank[N], height[N], belong[N], pos[N]; 8 char s[N], a[N]; 9 bool f[101]; 10 11 inline void build_sa() 12 { 13 int i, k, p; 14 for(i = 0; i < m; i++) buc[i] = 0; 15 for(i = 0; i < len; i++) buc[x[i] = s[i]]++; 16 for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 17 for(i = len - 1; i >= 0; i--) sa[--buc[x[i]]] = i; 18 for(k = 1; k <= len; k <<= 1) 19 { 20 p = 0; 21 for(i = len - 1; i >= len - k; i--) y[p++] = i; 22 for(i = 0; i < len; i++) if(sa[i] >= k) y[p++] = sa[i] - k; 23 for(i = 0; i < m; i++) buc[i] = 0; 24 for(i = 0; i < len; i++) buc[x[y[i]]]++; 25 for(i = 1; i < m; i++) buc[i] += buc[i - 1]; 26 for(i = len - 1; i >= 0; i--) sa[--buc[x[y[i]]]] = y[i]; 27 std::swap(x, y); 28 p = 1, x[sa[0]] = 0; 29 for(i = 1; i < len; i++) 30 x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p++; 31 if(p >= len) break; 32 m = p; 33 } 34 } 35 36 inline void build_height() 37 { 38 int i, j, k = 0; 39 for(i = 0; i < len; i++) rank[sa[i]] = i; 40 for(i = 0; i < len; i++) 41 { 42 if(!rank[i]) continue; 43 if(k) k--; 44 j = sa[rank[i] - 1]; 45 while(s[i + k] == s[j + k] && i + k < len && j + k < len) k++; 46 height[rank[i]] = k; 47 } 48 } 49 50 inline bool check(int k) 51 { 52 pos[0] = 0; 53 int i, cnt = 1; 54 memset(f, 0, sizeof(f)); 55 f[belong[sa[0]]] = 1; 56 for(i = 1; i < len; i++) 57 if(height[i] < k) 58 { 59 cnt = 1; 60 memset(f, 0, sizeof(f)); 61 f[belong[sa[i]]] = 1; 62 } 63 else if(!f[belong[sa[i]]]) 64 { 65 cnt += f[belong[sa[i]]] = 1; 66 if(cnt == (n >> 1) + 1) pos[++pos[0]] = sa[i]; 67 } 68 return pos[0]; 69 } 70 71 inline void solve() 72 { 73 int i, j, l = 1, r = len, mid, ans = 0; 74 while(l <= r) 75 { 76 mid = (l + r) >> 1; 77 if(check(mid)) max_num = pos[0], ans = mid, l = mid + 1; 78 else r = mid - 1; 79 } 80 if(ans) 81 { 82 for(i = 1; i <= max_num; putchar(‘\n‘), i++) 83 for(j = pos[i]; j < pos[i] + ans; j++) 84 putchar(s[j]); 85 putchar(‘\n‘); 86 } 87 else 88 { 89 putchar(‘?‘); 90 putchar(‘\n‘); 91 putchar(‘\n‘); 92 } 93 } 94 95 int main() 96 { 97 int i, k = 0, h; 98 while(scanf("%d", &n)) 99 { 100 if(!n) break; 101 h = 0; 102 m = 256; 103 len = 0; 104 memset(belong, -1, sizeof(belong)); 105 for(i = 0; i < n; i++) 106 { 107 scanf("%s", a); 108 for(k = 0; a[k] ^ ‘\0‘; k++) belong[len] = i, s[len++] = a[k]; 109 belong[len] = i; 110 s[len++] = h++; 111 } 112 len--; 113 build_sa(); 114 build_height(); 115 solve(); 116 } 117 return 0; 118 }
以上是关于[POJ3294]Life Forms(后缀数组)的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3294 Life Forms(后缀数组+二分答案)
POJ 3294 UVA 11107 Life Forms 后缀数组