zoukankan      html  css  js  c++  java
  • 后缀数组 POJ 3261 Milk Patterns

    题目链接

    题意:可重叠的 k 次最长重复子串。给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠。

    分析:与POJ 1743做法类似,先二分答案,height数组分段后统计 LCP>=m 的子串的个数。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    const int N = 2e4 + 5;
    int sa[N], rank[N], height[N];
    int t[N], t2[N], c[N];
    int a[N], A[N];
    
    void da(int *s, int n, int m) {
        int i, p, *x = t, *y = t2;
        for (i=0; i<m; ++i) c[i] = 0;
        for (i=0; i<n; ++i) c[x[i]=s[i]]++;
        for (i=1; i<m; ++i) c[i] += c[i-1];
        for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
        for (int k=1; k<=n; k<<=1) {
            for (p=0, i=n-k; i<n; ++i) y[p++] = i;
            for (i=0; i<n; ++i) if (sa[i] >= k) y[p++] = sa[i] - k;
            for (i=0; i<m; ++i) c[i] = 0;
            for (i=0; i<n; ++i) c[x[y[i]]]++;
            for (i=0; i<m; ++i) c[i] += c[i-1];
            for (i=n-1; i>=0; --i) sa[--c[x[y[i]]]] = y[i];
            std::swap (x, y);
            p = 1; x[sa[0]] = 0;
            for (i=1; i<n; ++i) {
                x[sa[i]] = (y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p - 1 : p++);
            }
            if (p >= n) break;
            m = p;
        }
    }
    
    void calc_height(int n) {
        int i, k = 0;
        for (i=0; i<n; ++i) rank[sa[i]] = i;
        for (i=0; i<n; ++i) {
            if (k) k--;
            int j = sa[rank[i]-1];
            while (a[i+k] == a[j+k]) k++;
            height[rank[i]] = k;
        }
    }
    
    int n, k;
    
    bool check(int m) {
        int cnt = 0;
        for (int i=1; i<n; ++i) {
            if (height[i] >= m) {
                cnt++;
                //height[i] = LCP (suffix (sa[i-1], sa[i]));
                if (cnt + 1 >= k) {
                    return true;
                }
            } else {
                cnt = 0;
            }
        }
        return false;
    }
    
    int main() {
        while (scanf ("%d%d", &n, &k) == 2) {
            for (int i=0; i<n; ++i) {
                scanf ("%d", a+i);
                A[i] = a[i];
            }
            std::sort (A, A+n);
            for (int i=0; i<n; ++i) {
                a[i] = std::lower_bound (A, A+n, a[i]) - A + 1;
            }
            a[n++] = 0;
            
            da (a, n, 20000);
            calc_height (n);
            
            int ans = 0;
            int left = 0, right = n - 1;
            while (left <= right) {
                int mid = left + right >> 1;
                if (check (mid)) {
                    ans = std::max (ans, mid);
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            printf ("%d
    ", ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    LeetCode Subsets II
    LeetCode Rotate Image
    LeetCode Palidrome Number
    LeetCode Generate Parentheses
    LeetCode Maximum Subarray
    LeetCode Set Matrix Zeroes
    LeetCode Remove Nth Node From End of List
    Linux Loop设备 使用
    Linux 文件系统大小调整
    LeetCode N-Queens II
  • 原文地址:https://www.cnblogs.com/Running-Time/p/5450040.html
Copyright © 2011-2022 走看看