zoukankan      html  css  js  c++  java
  • poj 3294 Life Forms

    题目传送门

      传送门I

      传送门II

    题目大意

      给定$n$个串,询问所有出现在严格大于$frac{n}{2}$个串的最长串。不存在输出'?'

      用奇怪的字符把它们连接起来。然后求sa,hei,二分答案,按mid分组。

      判断每一组存在的后缀属于的原串的种类数是不是存在那么多个。

      这个做法可以推广到多串求LCS,然后多个log,完美在SPOJ上T掉。

    Code

      1 /**
      2  * poj
      3  * Problem#3294
      4  * Accepted
      5  * Time: 391ms
      6  * Memory: 5024k
      7  */
      8 #include <iostream>
      9 #include <cstring>
     10 #include <cstdlib>
     11 #include <cstdio>
     12 #ifndef WIN32
     13 #define Auto "%lld"
     14 #else
     15 #define Auto "%I64d"
     16 #endif
     17 using namespace std;
     18 typedef bool boolean;
     19 #define ll long long
     20 
     21 #define pii pair<int, int>
     22 #define fi first
     23 #define sc second
     24 
     25 const int N = 1e5 + 105, M = 105;
     26 
     27 typedef class Pair3 {
     28     public:
     29         int x, y, id;
     30 
     31         Pair3() {    }
     32         Pair3(int x, int y, int id):x(x), y(y), id(id) {    }
     33 }Pair3;
     34 
     35 typedef class SuffixArray {
     36     protected: 
     37         Pair3 T1[N], T2[N];
     38         int cnt[N];
     39 
     40     public:
     41         int n;
     42         char *str;
     43         int sa[N], rk[N], hei[N];
     44 
     45         void set(int n, char* str) {
     46             this->n = n;
     47             this->str = str;
     48             memset(sa, 0, sizeof(sa));
     49             memset(rk, 0, sizeof(rk));
     50             memset(hei, 0, sizeof(hei));
     51         }
     52 
     53         void radix_sort(Pair3* x, Pair3* y) {
     54             int m = max(n, 256);
     55             memset(cnt, 0, sizeof(int) * m);
     56             for (int i = 0; i < n; i++)
     57                 cnt[x[i].y]++;
     58             for (int i = 1; i < m; i++)
     59                 cnt[i] += cnt[i - 1];
     60             for (int i = 0; i < n; i++)
     61                 y[--cnt[x[i].y]] = x[i];
     62 
     63             memset(cnt, 0, sizeof(int) * m);
     64             for (int i = 0; i < n; i++)
     65                 cnt[y[i].x]++;
     66             for (int i = 1; i < m; i++)
     67                 cnt[i] += cnt[i - 1];
     68             for (int i = n - 1; ~i; i--)
     69                 x[--cnt[y[i].x]] = y[i];
     70         }
     71 
     72         void build() {
     73             for (int i = 0; i < n; i++)
     74                 rk[i] = str[i];
     75             for (int k = 1; k < n; k <<= 1) {
     76                 for (int i = 0; i + k < n; i++)
     77                     T1[i] = Pair3(rk[i], rk[i + k], i);
     78                 for (int i = n - k; i < n; i++)
     79                     T1[i] = Pair3(rk[i], 0, i);
     80                 radix_sort(T1, T2);
     81                 int diff = 0;
     82                 rk[T1[0].id] = 0;
     83                 for (int i = 1; i < n; i++)
     84                     rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff);
     85                 if (diff == n - 1)
     86                     break;
     87             }
     88             for (int i = 0; i < n; i++)
     89                 sa[rk[i]] = i;
     90         }
     91 
     92         void get_height() {
     93             for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) {
     94                 if (rk[i]) {
     95                     j = sa[rk[i] - 1];
     96                     while (i + k < n && j + k < n && str[i + k] == str[j + k])    k++;
     97                     hei[rk[i]] = k;
     98                 }
     99             }        
    100         }
    101 
    102         const int& operator [] (int p) {
    103             return sa[p];
    104         }
    105 
    106         const int& operator () (int p) {
    107             return hei[p];
    108         }
    109 }SuffixArray;
    110 
    111 int n, m, K;
    112 char S[N];
    113 int suf[N];
    114 SuffixArray sa;
    115 
    116 inline boolean init() {
    117     scanf("%d", &m);
    118     if (!m)
    119         return false;
    120     K = (m >> 1) + 1;
    121     scanf("%s", S);
    122     n = strlen(S);
    123     for (int i = 1; i < m; i++) {
    124         S[n++] = '?';
    125         scanf("%s", S + n);
    126         n += strlen(S + n);
    127     }
    128     suf[n] = 0;
    129     for (int i = n - 1; ~i; i--)
    130         suf[i] = suf[i + 1] + (S[i] == '?');
    131     sa.set(n, S);
    132     return true;
    133 }
    134 
    135 int chk_clock = 0;
    136 int vis[M];
    137 
    138 boolean check(int L, int R, int mid) {    // [L, R)
    139     if (R - L < K)
    140         return false;
    141     if (suf[sa[L]] - suf[sa[L] + mid])
    142         return false;
    143     chk_clock++;
    144     int rt = 0;
    145     for (int i = L; i < R && rt < K; i++)
    146         if (vis[suf[sa[i]]] != chk_clock)
    147             vis[suf[sa[i]]] = chk_clock, rt++;
    148     return rt >= K;
    149 }
    150 
    151 boolean check(int mid) {
    152     int lst = 0;
    153     boolean rt = false;
    154     for (int i = 1; i < n && !rt; i++)
    155         if (sa(i) < mid)
    156             rt |= check(lst, i, mid), lst = i;
    157     if (!rt)
    158         rt |= check(lst, n, mid);
    159     return rt;
    160 }
    161 
    162 void output(int L, int R, int res) {
    163     if (!check(L, R, res))
    164         return;
    165     for (int i = sa[L], j = 0; j < res; j++)
    166         putchar(S[i + j]);
    167     putchar('
    ');
    168 }
    169 
    170 inline void solve() {
    171     chk_clock = 0;
    172     memset(vis, 0, sizeof(vis));
    173     
    174     sa.build();
    175     sa.get_height();
    176 
    177     int l = 1, r = n / m, mid;
    178     while (l <= r) {
    179         mid = (l + r) >> 1;
    180         if (check(mid))
    181             l = mid + 1;
    182         else
    183             r = mid - 1;
    184     }
    185     
    186     if (!(--l))
    187         puts("?");
    188     else {
    189         int lst = 0;
    190         for (int i = 1; i < n; i++)
    191             if (sa(i) < l)
    192                 output(lst, i, l), lst = i;
    193         output(lst, n, l);
    194     }
    195     puts("");
    196 }
    197 
    198 int main() {
    199     while (init())
    200         solve();
    201     return 0;
    202 }
  • 相关阅读:
    关于:HTTP Header -> Content-Type: text/plain Cache-Control: no-cache IE浏览器弹出错误下载对话
    Linux 基础入门
    Java 并发——多线程基础
    JavaScript面向对象
    理解JavaScript的定时器与回调机制
    理解领域模型
    邮件协议基础知识
    Java NIO 学习笔记
    Java Socket 学习笔记
    HTTP协议基础与实验
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9762996.html
Copyright © 2011-2022 走看看