• [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('
    '), i++)
     83             for(j = pos[i]; j < pos[i] + ans; j++)
     84                 putchar(s[j]);
     85         putchar('
    ');
     86     }
     87     else
     88     {
     89         putchar('?');
     90         putchar('
    ');
     91         putchar('
    ');
     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] ^ ''; 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
  • 相关阅读:
    IO流图片加密。
    IO流(流的标准处理异常代码)
    字节流写出中文。
    字节流读取中文。
    IO流BufferedInputStream和BufferOutputStream拷贝。
    Collection集合。
    《C#并发编程经典实例》学习笔记—2.3 报告任务
    《C#并发编程经典实例》学习笔记—2.2 返回完成的任务
    《C#并发编程经典实例》学习笔记—2.1 暂停一段时间
    《C#并发编程经典实例》学习笔记—异步编程关键字 Async和Await
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6999125.html
Copyright © 2020-2023  润新知