spoj687 【重复次数最多的连续重复子串】

 题目链接:https://vjudge.net/problem/SPOJ-REPEATS

 推荐博客:https://blog.csdn.net/queuelovestack/article/details/53031731

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

const int MAX = 200010;
const int SIGMA_SIZE = 256;
int cntA[MAX], cntB[MAX], sa[MAX], tsa[MAX], A[MAX], B[MAX], height[MAX], Rank[MAX];
int n, data[MAX];
int bucket[SIGMA_SIZE];

char s[MAX];
void get_SA(char *ch) {
    for (int i = 0; i < SIGMA_SIZE; i++) bucket[i] = 0;
    for (int i = 1; i <= n; i++) bucket[ch[i - 1]]++;
    for (int i = 1; i < SIGMA_SIZE; i++) bucket[i] += bucket[i - 1];
    for (int i = n; i; i--) sa[bucket[ch[i - 1]]--] = i;
    Rank[sa[1]] = 1;
    for (int i = 2; i <= n; i++) {
        Rank[sa[i]] = Rank[sa[i - 1]];
        if (ch[sa[i] - 1] != ch[sa[i - 1] - 1]) Rank[sa[i]]++;
    }
    for (int l = 1; Rank[sa[n]] < n; l <<= 1) {
        memset(cntA, 0, sizeof(cntA));
        memset(cntB, 0, sizeof(cntB));
        for (int i = 1; i <= n; i++) {
            cntA[A[i] = Rank[i]]++;
            cntB[B[i] = (i + l <= n) ? Rank[i + l] : 0]++;
        }
        for (int i = 1; i <= n; i++) cntB[i] += cntB[i - 1];
        for (int i = n; i; i--) tsa[cntB[B[i]]--] = i;
        for (int i = 1; i <= n; i++) cntA[i] += cntA[i - 1];
        for (int i = n; i; i--) sa[cntA[A[tsa[i]]]--] = tsa[i];
        Rank[sa[1]] = 1;
        for (int i = 2; i <= n; i++) {
            Rank[sa[i]] = Rank[sa[i - 1]];
            if (A[sa[i]] != A[sa[i - 1]] || B[sa[i]] != B[sa[i - 1]]) Rank[sa[i]]++;
        }
    }
    for (int i = 1, j = 0; i <= n; i++) {
        if (j) j--;
        while (ch[i + j - 1] == ch[sa[Rank[i] - 1] + j - 1]) j++;
        height[Rank[i]] = j;
    }
}

int dp[MAX][25];
void RMQ(){
    for(int i = 1; i <= n; i++) dp[i][0] = height[i];
    for(int i = 1; i < 25; i++){
        for(int j = 1; j + (1 << i) - 1 <= n; j++){
            dp[j][i] = min(dp[j][i-1],dp[(j+(1<<(i-1)))][i-1]);
        }
    }
}
int q_min(int x,int y){
    int k = (int)((log(y - x + 1) * 1.0) / log(2.0));
    return min(dp[x][k],dp[y - (1<b)
        swap(a,b);
    return q_min(a+1,b);
}
int main() {
   // freopen("a.txt","r",stdin);
    ios::sync_with_stdio(0);
    int T;
    cin>>T;
    while(T--) {
        cin>>n;
        for(int i = 0; i < n; i++) cin>>s[i];
        get_SA(s);
        RMQ();
        int ans = 1;
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j+i < n; j+=i) {
                int k = calprefix(j,j+i);
                int now = (k/i)+1;
                if(k%i!=0) {
                    int last = i-(k%i);
                    if(calprefix(j-last,j+i-last)>=last) now++;
                }
                ans = max(ans,now);
            }
        }
        cout<

 

你可能感兴趣的:(后缀数组)