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

 

以上是关于[POJ3294]Life Forms(后缀数组)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 3294 Life Forms(后缀数组+二分答案)

POJ 3294 UVA 11107 Life Forms 后缀数组

POJ3294Life Forms(后缀数组,二分)

[POJ3294]Life Forms(后缀数组)

POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]

Life Forms POJ - 3294