首页 > 代码库 > [POJ3294]Life Forms(后缀数组)

[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 }
View Code

 

[POJ3294]Life Forms(后缀数组)