zoukankan      html  css  js  c++  java
  • HDU5558 Alice's Classified Message(合肥区域赛 后缀数组)

    当初合肥区域赛的题(现场赛改了数据范围就暴力过了),可惜当初后缀数组算法的名字都没听过,现在重做下。

    i从1到n - 1,每次枚举rank[i]附近的排名,并记录当起点小于i时的LCP(rank[i], d)的最大值,或是在LCP不变时更新起点。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    const int N = 110008, INF = 0x3F3F3F3F;
    
    int val[N], ws0[N], wa[N], wb[N];
    int sa[N], rk[N], height[N];
    
    char str[N];
    
    bool cmp(int str[], int a, int b, int l){
        return str[a] == str[b] && str[a + l] == str[b + l];
    }
    
    void da(char str[], int n, int m){
        int *x = wa, *y = wb;
    
        memset(ws0, 0, sizeof(ws0));
        for(int i = 0; i < n; i++)
            ws0[x[i] = str[i]]++;
    
        for(int i = 1; i < m; i++)
            ws0[i] += ws0[i - 1];
    
        for(int i = n - 1; i >= 0; i--)
            sa[--ws0[ x[i]] ] = i;
    
        for(int j = 1, p = 1; p < n; j *= 2, m = p){
            p = 0;
            for(int i = n - j; i < n; i++)
                y[p++] = i;
            for(int i = 0; i < n; i++)
                if(sa[i] >= j)
                    y[p++] = sa[i] - j;
            for(int i = 0; i < n; i++)
                val[i] = x[ y[i] ];
    
            memset(ws0, 0, sizeof(ws0));
            for(int i = 0; i < n; i++)
                ws0[val[i]]++;
    
            for(int i = 1; i < m; i++)
                ws0[i] += ws0[i - 1];
    
            for(int i = n - 1; i >= 0; i--)
                sa[--ws0[ val[i] ]] = y[i];
    
            swap(x, y);
            x[sa[0]] = 0;
            p = 1;
            for(int i = 1; i < n; i++)x[sa[i]] = cmp(y, sa[i - 1], sa[i], j)? p - 1:p++;
        }
    }
    
    void calHeight(char str[], int n){
        for(int i = 1; i <= n; i++){
            rk[ sa[i] ] = i;
        }
        int k = 0;
        for(int i = 0; i < n; i++){
            if(k){
                k--;
            }
            int j = sa[rk[i] - 1];
            while(str[i + k] == str[j + k]){
                k++;
            }
            height[rk[i]] = k;
        }
    }
    
    int rmq[N][20], tab[N];
    
    void initaskRMQ(int n){
        tab[1] = 0;
        for(int i = 2; i <= n; i++){
            tab[i] = ( (i & (i - 1)) == 0)? tab[i - 1] + 1:tab[i - 1];
        }
        for(int i = 1; i <= n; i++){
            rmq[i][0] = height[i];
        }
        for(int i = 1; i <= tab[n]; i++){
            for(int j = 1; j <= n + 1 - (1 << i); j++){
                int a = rmq[j][i - 1];
                int b = rmq[j + (1 <<(i - 1))][i - 1];
                rmq[j][i] = min(a, b);
            }
        }
    }
    
    int askRMQ(int a, int b){
        int k = tab[b -a + 1];
        b -= (1 << k ) - 1;
        return min(rmq[a][k], rmq[b][k]);
    }
    
    int LCP(int a, int b){
        if(a > b){
            swap(a, b);
        }
        return askRMQ(a + 1, b);
    }
    
    
    int main(){
        int t;
        cin>>t;
        for(int cas = 1; cas <= t; cas++){
            scanf("%s", str);
            int n = strlen(str);
            da(str, n + 1, 'z' + 1);
            calHeight(str, n);
    
            initaskRMQ(n);
            printf("Case #%d:
    ", cas);
            printf("%d %d
    ", -1, str[0]);
            for(int i = 1; i < n; ){
                int st = INF, k = 1;
                int d = rk[i] + 1;
                int tp;
                while(d <= n && (tp = LCP(d, rk[i])) >= k){
                    if(sa[d] < i){
                        if(tp > k){
                            k = tp;
                            st = sa[d];
                        }else{
                            if(sa[d] < st){
                                st = sa[d];
                            }
                        }
                    }
                    d++;
                }
    
                d = rk[i] - 1;
                while(d >= 1 && (tp = LCP(d, rk[i])) >= k){
                    if(sa[d] < i){
                        if(tp > k){
                            k = tp;
                            st = sa[d];
                        }else{
                            if(sa[d] < st){
                                st = sa[d];
                            }
                        }
                    }
                    d--;
                }
                if(st < i){
                    printf("%d %d
    ", k, st);
                    i += k;
                }else{
                    printf("%d %d
    ", -1, (int)str[i]);
                    i++;
                }
            }
        }
        return 0;
    }
    

      加油吧! fighting!!!

  • 相关阅读:
    回答提出的问题1-17章
    《构建之法》第13-17章读书笔记
    读《一个程序员的生命周期》有感
    构建之法的第十、十一、十二章读书笔记
    阅读《构建之法》第8,9,10章
    5.2-5.3
    作业5.1测试与封装
    读《构建之法》5.6.7 思考
    读《构建之法》的思考
    作业2 结对思则运算
  • 原文地址:https://www.cnblogs.com/IMGavin/p/5735902.html
Copyright © 2011-2022 走看看