zoukankan      html  css  js  c++  java
  • poj2406(后缀数组)

    poj2406

    题意

    给出一个字符串,它是某个子串重复出现得到的,求子串最多出现的次数。

    分析

    后缀数组做的话得换上 DC3 算法。

    那么子串的长度就是 (len - height[rnk[0]]) (当然必须保证字符串总长是子串长度的整数倍)。
    如果字符串是 ababab,考虑 (height[rnk[0]]) 的意义,那么就是ababab和它的后缀排序后前面一个的后缀串的最大公共前缀长度,它前面的是abab,因为这个后缀串在比较的时候是以abab00的形式出现的,它后面接的只能是ababab,那么缺少的正好是一个子串。

    code

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
    #define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2)
    using namespace std;
    const int N = 1000005;
    int wa[N], wb[N], ws[N], wv[N], sa[N * 3];
    int rnk[N * 3], height[N * 3], s[N];
    char str[N];
    
    int c0(int *r, int a, int b) {
        return r[a] == r[b] && r[a + 1] == r[b + 1] && r[a + 2] == r[b + 2];
    }
    
    int c12(int k, int *r, int a, int b) {
        if (k == 2)
            return r[a] < r[b] || r[a] == r[b] && c12(1, r, a + 1, b + 1);
        return r[a] < r[b] || r[a] == r[b] && wv[a + 1] < wv[b + 1];
    }
    
    void Rsort(int *r, int *a, int *b, int n, int m) {
        for (int i = 0; i < n; i++) wv[i] = r[a[i]];
        for (int i = 0; i < m; i++) ws[i] = 0;
        for (int i = 0; i < n; i++) ws[wv[i]]++;
        for (int i = 1; i < m; i++) ws[i] += ws[i - 1];
        for (int i = n - 1; i >= 0; i--) b[--ws[wv[i]]] = a[i];
    }
    
    void dc3(int *r, int *sa, int n, int m) {
        int i, j, *rn = r + n, *san = sa + n, ta = 0, tb = (n + 1) / 3, tbc = 0, p;
        r[n] = r[n + 1] = 0;
        for (i = 0; i < n; i++) if (i % 3 != 0) wa[tbc++] = i;
        Rsort(r + 2, wa, wb, tbc, m);
        Rsort(r + 1, wb, wa, tbc, m);
        Rsort(r, wa, wb, tbc, m);
        for (p = 1, rn[F(wb[0])] = 0, i = 1; i < tbc; i++)
            rn[F(wb[i])] = c0(r, wb[i - 1], wb[i]) ? p - 1 : p++;
        if (p < tbc) dc3(rn, san, tbc, p);
        else for (i = 0; i < tbc; i++) san[rn[i]] = i;
        for (i = 0; i < tbc; i++) if (san[i] < tb) wb[ta++] = san[i] * 3;
        if (n % 3 == 1) wb[ta++] = n - 1;
        Rsort(r, wb, wa, ta, m);
        for (i = 0; i < tbc; i++) wv[wb[i] = G(san[i])] = i;
        for (i = 0, j = 0, p = 0; i < ta && j < tbc; p++)
            sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
        for (; i < ta; p++) sa[p] = wa[i++];
        for (; j < tbc; p++) sa[p] = wb[j++];
    }
    
    void calheight(int *r, int *sa, int n) {
        int i, j, k = 0;
        for (i = 1; i <= n; i++) rnk[sa[i]] = i;
        for (i = 0; i < n; height[rnk[i++]] = k)
            for (k ? k-- : 0, j = sa[rnk[i] - 1]; r[i + k] == r[j + k]; k++);
    }
    
    int main() {
        while (scanf("%s", str) == 1 && str[0] != '.') {
            int len = strlen(str);
            for (int i = 0; i < len; i++)
                s[i] = str[i] - 'a' + 1;
            s[len] = 0;
            dc3(s, sa, len + 1, 105);
            calheight(s, sa, len);
            /* 如果不懂打印出来看一下
            for(int i = 1; i <= len; i++) {
                printf("%s
    ", str + sa[i]);
            }
            */
            int aa = len - height[rnk[0]];
            int ans = 1;
            if(len % aa == 0) {
                ans = len / aa;
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能
    linux irq 自动探测
    gpio子系统和pinctrl子系统(下)
    gpio子系统和pinctrl子系统(中)
    gpio子系统和pinctrl子系统(上)
    linux驱动基础系列--linux spi驱动框架分析
    linux驱动基础系列--linux rtc子系统
    linux驱动基础系列--Linux I2c驱动分析
    camera驱动框架分析(上)
    camera驱动框架分析(中)
  • 原文地址:https://www.cnblogs.com/ftae/p/7214713.html
Copyright © 2011-2022 走看看