SP687 REPEATS - Repeats

Posted maomao9173

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SP687 REPEATS - Repeats相关的知识,希望对你有一定的参考价值。

给定字符串,求重复次数最多的连续重复子串。

题目很简单,被细节坑惨了。。。

前置的一个推论:请看这里。

#include <bits/stdc++.h>
using namespace std;

const int N = 50010;

struct String {
    char s[N]; int st[N][17];
    
    int n, m, sa[N], tp[N], rk[N], _rk[N], bin[N], height[N];
    
    void clear () {
        memset (s, 0, sizeof (s));
        memset (sa, 0, sizeof (sa));
        memset (tp, 0, sizeof (tp));
        memset (rk, 0, sizeof (rk));
        memset (st, 0, sizeof (st));
        memset (_rk, 0, sizeof (_rk));
        memset (bin, 0, sizeof (bin));
        memset (height, 0, sizeof (height));
    }
    
    void base_sort () {
        for (int i = 0; i <= m; ++i) bin[i] = 0;
        for (int i = 1; i <= n; ++i) bin[rk[tp[i]]]++;
        for (int i = 1; i <= m; ++i) bin[i] += bin[i - 1];
        for (int i = n; i >= 1; --i) sa[bin[rk[tp[i]]]--] = tp[i];
    }
    
    void suffix_sort () {
        m = 255; ;
        for (int i = 1; i <= n; ++i) {
            tp[i] = i, rk[i] = s[i];
        }
        base_sort ();
        for (int w = 1; w <= n; w <<= 1) {
            int cnt = 0;
            for (int i = n - w + 1; i <= n; ++i) tp[++cnt] = i;
            for (int i = 1; i <= n; ++i) if (sa[i] > w) tp[++cnt] = sa[i] - w;
            base_sort ();
            memcpy (_rk, rk, sizeof (rk));
            rk[sa[1]] = cnt = 1;
            for (int i = 2; i <= n; ++i) {
                rk[sa[i]] = _rk[sa[i]] == _rk[sa[i - 1]] && _rk[sa[i] + w] == _rk[sa[i - 1] + w] ? cnt : ++cnt;
            }
            if (cnt == n) break;
            m = cnt;
        }
        int k = 0;
        for (int i = 1; i <= n; ++i) {
            if (k != 0) --k;
            int j = sa[rk[i] - 1];
            while (s[i + k] == s[j + k]) ++k;
            height[rk[i]] = k; 
        }
        int mx = log2 (n);
        for (int i = 1; i <= n; ++i) {
            st[i][0] = height[i];
        }
        for (int i = 1; i <= mx; ++i) {
            for (int j = 1; j + (1 << i) - 1 <= n; ++j) {
                st[j][i] = min (st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
            }
        }
    } 
    
    int lcp (int l, int r) {
        if (l == r) return n - l + 1;
        l = rk[l], r = rk[r];
        if (l > r) swap (l, r); ++l;
        if (l > r) return 0;
        int mx = log2 (r - l + 1);
        return min (st[l][mx], st[r - (1 << mx) + 1][mx]);
    }
}s1, s2;

int T, n; char s[N];

int main () {
    cin >> T;
    while (T--) {
        int ans = 0;
        cin >> n; s1.n = s2.n = n;
        s1.clear (); s2.clear ();
        for (int i = 1; i <= n; ++i) {
            cin >> s[i];
            s1.s[i] = s[i];
            s2.s[n - i + 1] = s[i];
        }
        s1.suffix_sort ();
        s2.suffix_sort ();
        for (int len = 1; len <= n; ++len) {//枚举重复子串的长度 
            for (int p = 1; p + len <= n; p += len) {
                int K = s1.lcp (p, p + len) + s2.lcp (n - (p) + 1, n - (p + len) + 1) - 1;
                ans = max (ans, K / len + 1);
            }
        }
        cout << max (ans, 1) << endl;
    }
}

以上是关于SP687 REPEATS - Repeats的主要内容,如果未能解决你的问题,请参考以下文章

题解 SP687 REPEATS - Repeats

SPOJ 687 Repeats(后缀数组+ST表)

SPOJ - REPEATS Repeats (后缀数组)

Repeats SPOJ - REPEATS (AC自动机 + RMQ)

SPOJ REPEATS - Repeats - 后缀数组

spoj687 后缀数组重复次数最多的连续重复子串