• 暑假集训 || 后缀三连


    orz……

    后缀数组orz……

    例如:n = 8;

    num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ }; 注意 num 最后一位为 0,其他 大于 0
    rank[] = 4, 6, 8, 1, 2, 3, 5, 7, 0 ;rank[0 n-1] 为有效值,rank[n] 必定为 0 无效值
    sa[] = 8, 3, 4, 5, 0, 6, 1, 7, 2 ;sa[1 n] 为有效值,sa[0] 必定为 n 是 无效值
    height[]= 0, 0, 3, 2, 3, 1, 2, 0, 1 ;height[2 n] 为有效值

    const int maxn = 100010;
    int t1[maxn], t2[maxn], c[maxn];
    bool cmp(int *r, int a, int b, int l)
    {
        return r[a] == r[b] && r[a+l] == r[b+l];
    }
    void da(int str[], int sa[], int rank[], int height[], int n, int m)
    {
        n++;
        int p, *x = t1, *y = t2;
        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) c[x[i] = str[i]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];
        for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
        for(int j = 1; j <= n; j <<= 1)
        {
            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 < m; i++) c[i] = 0;
            for(int i = 0; i < n; i++) c[x[y[i]]]++;
            for(int i = 1; i < m; i++) c[i] += c[i-1];
            for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
            swap(x, y);
            p = 1, x[sa[0]] = 0;
            for(int i = 1; i < n; i++)
                x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;
            if(p >= n) break;
            m = p;
        }
        int k = 0;
        n--;
        for(int i = 0; i <= n; i++) rank[sa[i]] = i;
        for(int i = 0; i < n; i++)
        {
            if(k) k--;
            int j = sa[rank[i]-1];
            while(str[i+k] == str[j+k]) k++;
            height[rank[i]] = k;
        }
    }
    int rank[maxn], height[maxn], h[maxn];
    int RMQ[maxn], mm[maxn];
    int best[20][maxn];
    void initRMQ(int n)
    {
        mm[0] = -1;
        for(int i = 1; i <= n; i++)
            mm[i] = ((i & (i-1)) == 0) ? mm[i-1]+1 : mm[i-1];
        for(int i = 1; i <= n; i++) best[0][i] = i;
        for(int i = 1; i <= mm[n]; i++)
            for(int j = 1; j + (1<<i) - 1 <= n; j++)
            {
                int a = best[i-1][j];
                int b = best[i-1][j + (1 << (i-1))];
                if(RMQ[a] < RMQ[b]) best[i][j] = a;
                else best[i][j] = b;
            }
    }
    int askRMQ(int a, int b)
    {
        int t;
        t = mm[b-a+1];
        b -= (1<<t) - 1;
        a = best[t][a], b = best[t][b];
        return RMQ[a] < RMQ[b] ? a : b;
    }
    int lcp(int a, int b)
    {
        a = rank[a], b = rank[b];
        if(a > b) swap(a, b);
        return height[askRMQ(a+1, b)];
    }
    View Code

    题意:给一个字符串,以每一位为开头环形的读,把len种读法排序,排序后每种读法最后一位连在一起就是答案

    思路:把数组接一段在后面,sa[i]的前一位就是排序后的最后一位。。

    int main()
    {
        scanf(" %s", str);
        int len = strlen(str);
        for(int i = 0; i < len; i++) str[i+len] = str[i];
        len = len<<1;
        da(str, sa, rank, height, len, 128);
        int idx = 0;
        for(int i = 1; i <= len; i++)
            if(sa[i] < (len>>1)) ans[idx++] = str[sa[i] + (len>>1) - 1];
        ans[len>>1] = '';
        printf("%s
    ", ans);
        return 0;
    }
    View Code
  • 相关阅读:
    (转)使用 sys 帳號登入 E900 Standalone 安裝的 Oracle 資料庫
    Eclipse中main函数由控制台输入参数为空的处理
    orcle10Concepts笔记
    根据某个时间字符串获取上个月的时间
    eclipse导入java项目方法及出现问题
    好用的网址
    收藏网址
    Eclipse中main函数由控制台输入参数并接收
    java.io读写文本
    ClassNotFoundException处理
  • 原文地址:https://www.cnblogs.com/pinkglightning/p/9565720.html
Copyright © 2020-2023  润新知