zoukankan      html  css  js  c++  java
  • UVA11107 Life Forms --- 后缀数组

    UVA11107 Life Forms

    题目描述:

    求出出现在一半以上的字符串内的最长字符串。

    数据范围:

    (sum len(string) <= 10^{5})

    非常坑的题目。

    思路非常好想。

    构造出后缀数组。

    二分出(len)后用(height)分组

    记(bel(i))表示排名为(i)后缀属于哪一个串

    当同一组内的不同的(bel(i))出现了(n/2)时,本组内有一组解。

    注意:

    每行数据间要打一个空行

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define sid 200050
    #define ri register int
    using namespace std;
    
    template <typename re>
    inline void upmax(re &a, re b) { if(a < b) a = b; }
    
    int Tt, n, ml, ned;
    char s[sid];
    int bel[sid], sc[sid];
    int flag[200];
    int sa[sid], rk[sid], cnt[sid], p1[sid], p2[sid], ht[sid];
    
    inline void Suffix() {
        int m = 128;
        int *t1 = p1, *t2 = p2;
        for(ri i = 1; i <= n; i ++) sc[i] = (s[i] == 1) ? ++ m : s[i];
        for(ri i = 1; i <= n; i ++) t1[i] = sc[i];
        for(ri i = 1; i <= m; i ++) cnt[i] = 0;
        for(ri i = 1; i <= n; i ++) cnt[t1[i]] ++;
        for(ri i = 1; i <= m; i ++) cnt[i] += cnt[i - 1];
        for(ri i = n; i >= 1; i --) sa[cnt[t1[i]] --] = i;
        for(ri k = 1; k <= n; k <<= 1) {
            int p = 0;
            for(ri i = 0; i <= m; i ++) t2[i] = 0;
            for(ri i = n - k + 1; i <= n; i ++) t2[++ p] = i;
            for(ri i = 1; i <= n; i ++) if(sa[i] > k) t2[++ p] = sa[i] - k;
            for(ri i = 1; i <= m; i ++) cnt[i] = 0;
            for(ri i = 1; i <= n; i ++) cnt[t1[t2[i]]] ++;
            for(ri i = 1; i <= m; i ++) cnt[i] += cnt[i - 1];
            for(ri i = n; i >= 1; i --) sa[cnt[t1[t2[i]]] --] = t2[i];
            swap(t1, t2); t1[sa[1]] = p = 1;
            for(ri i = 2; i <= n; i ++) 
            t1[sa[i]] = (t2[sa[i]] == t2[sa[i - 1]] && t2[sa[i] + k] == t2[sa[i - 1] + k]) ? p : ++ p;
            m = p; if(p >= n) break; 
        }
        for(ri i = 1; i <= n; i ++) rk[sa[i]] = i;
        ri k = 1, j;
        for(ri i = 1; i <= n; i ++) {
            if(k) k --;
            j = sa[rk[i] - 1];
            while(sc[j + k] == sc[i + k]) k ++;
            ht[rk[i]] = k;
        } 
    }
    
    inline bool Check(int htk) {
        int cnt = 0, tim = 0;
        memset(flag, 0, sizeof(flag));
        for(ri i = 1; i <= n; i ++) {
            if(ht[i] < htk) cnt = 0, ++ tim;
            if(flag[bel[sa[i]]] != tim && bel[sa[i]]) cnt ++, flag[bel[sa[i]]] = tim;
            if(cnt >= ned) return 1;
        }
        return 0;
    }
    
    inline int Binary() {
        int l = 1, r = ml, ans = -1;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(Check(mid)) l = mid + 1, ans = mid;
            else r = mid - 1;
        }
        return ans;
    }
    
    inline void Get_Ans(int op) {
        if(op == -1) {
            printf("?
    ");
            return;
        }
        memset(flag, 0, sizeof(flag));
        int cnt = 0, tim = 0, fag;
        for(ri i = 1; i <= n; i ++) {
            if(ht[i] < op) fag = 0, cnt = 0, ++ tim;
            if(flag[bel[sa[i]]] != tim && bel[sa[i]]) cnt ++, flag[bel[sa[i]]] = tim;
            if(cnt >= ned && !fag) {
                int k = sa[i];
                for(ri j = 1; j <= op; j ++) printf("%c", s[k + j - 1]);
                printf("
    ");
                cnt = 0; fag = 1;
            }
        }
    }
    
    int main() {
        bool pe = 0;
        while(scanf("%d", &Tt) == 1 && Tt) {
            if(pe) printf("
    "); pe = 1;
            n = ml = 0; ned = Tt / 2 + 1;
            memset(s, 0, sizeof(s));
            memset(bel, 0, sizeof(bel));
            for(ri i = 1; i <= Tt; i ++) {
                scanf("%s", s + 1 + n);
                int nl = strlen(s + 1 + n);
                for(ri j = n + 1; j <= n + nl; j ++) bel[j] = i;
                upmax(ml, nl); n += nl; s[++ n] = 1;
            }
            if(Tt != 1) {
                Suffix();
                int ans = Binary();
                Get_Ans(ans);
            }
            else {
                for(ri j = 1; j <= n - 1; j ++) printf("%c", s[j]);
                printf("
    ");
            }
        }
        return 0;
    }
    打开有惊喜
  • 相关阅读:
    淘宝客之 API调用实例讲解
    15个哲理小故事
    淘宝客之 淘宝客类目URL获取
    应广大淘宝客支持者 发布CHM API文档一份 鄙视官方没有离线文档
    淘宝客开发知识 开发前准备与基础知识
    富人和穷人间存在的十二个致命差异
    侧边栏
    半颗星星评分
    让DIV动起来
    软件项目开发过程中主要遇到的核心问题小结
  • 原文地址:https://www.cnblogs.com/reverymoon/p/8971188.html
Copyright © 2011-2022 走看看