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


    REPEATS - Repeats

    no tags 

    A string s is called an (k,l)-repeat if s is obtained by concatenating k>=1 times some seed string t with length l>=1. For example, the string

    s = abaabaabaaba

    is a (4,3)-repeat with t = aba as its seed string. That is, the seed string t is 3 characters long, and the whole string s is obtained by repeating t 4 times.

    Write a program for the following task: Your program is given a long string u consisting of characters ‘a’ and/or ‘b’ as input. Your program must find some (k,l)-repeat that occurs as substring within u with k as large as possible. For example, the input string

    u = babbabaabaabaabab

    contains the underlined (4,3)-repeat s starting at position 5. Since u contains no other contiguous substring with more than 4 repeats, your program must output the maximum k.

    Input

    In the first line of the input contains H- the number of test cases (H <= 20). H test cases follow. First line of each test cases is n - length of the input string (n <= 50000), The next n lines contain the input string, one character (either ‘a’ or ‘b’) per line, in order.

    Output

    For each test cases, you should write exactly one interger k in a line - the repeat count that is maximized.

    Example

    Input:
    1
    17
    b
    a
    b
    b
    a
    b
    a
    a
    b
    a
    a
    b
    a
    a
    b
    a
    b

    Output:
    4
    题意:
    求重复次数最多的连续重复子串。
     
    思路:
    可以先枚举重复子串的长度L,然后求长度为 L 的子串最多能连续出现几次。
    假设在原字符串中连续出 现 2 次,记这个子字符串为 S,那么 S 肯定包括了字符 r[0], r[L], r[L*2],
    r[L*3], ……中的某相邻的两个。所以只须看字符 r[L*i]和 r[L*(i+1)]往前和
    往后各能匹配到多远,记这个总长度为 K,那么这里连续出现了 K/L+1 次。最后
    看最大值是多少。
    对于后面的那部分可以根据height[]直接求得。对于前面的那部分
    先求后面部分减去长度L的x个子串后,是否还有。如果还有那么这一部分肯定属于前面。
    这样L - (后面部分长度)%L就是前面部分的长度tp,然后判断 r[L* i] - tp 和 r[L* i] - tp + L的公共前缀,
    如果长度大于等于r[L*i]和r[L*(i+1)]的公共长度,那么前面一定只是有1.
     
    /*
     * Author:  sweat123
     * Created Time:  2016/6/29 15:28:42
     * File Name: main.cpp
     */
    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<time.h>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define INF 1<<30
    #define MOD 1000000007
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define pi acos(-1.0)
    using namespace std;
    const int MAXN = 50010;
    int wa[MAXN],wb[MAXN],wc[MAXN],n,height[MAXN],Rank[MAXN],r[MAXN],sa[MAXN];
    char s[MAXN];
    void da(int *r,int *sa,int n,int m){
        int *x = wa,*y = wb;
        for(int i = 0; i < m; i++)wc[i] = 0;
        for(int i = 0; i < n; i++)wc[x[i] = r[i]] ++;
        for(int i = 0; i < m; i++)wc[i] += wc[i-1];
        for(int i = n - 1; i >= 0; i--)sa[--wc[x[i]]] = i;
        for(int k = 1,p = 1; p < n; m = p,k <<= 1){
            p = 0;
            for(int i = n - k; i < n; i++)y[p++] = i;
            for(int i = 0; i < n; i++)if(sa[i] >= k)y[p++] = sa[i] - k;
            for(int i = 0; i < m; i++)wc[i] = 0;
            for(int i = 0; i < n; i++)wc[x[y[i]]] ++;
            for(int i = 0; i < m; i++)wc[i] += wc[i-1];
            for(int i = n - 1; i >= 0; i--)sa[--wc[x[y[i]]]] = y[i];
            swap(x,y);
            p = 1;
            x[sa[0]] = 0;
            for(int i = 1; i < n; i++){
                x[sa[i]] = (y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k])?p-1:p++;
            }
        }
    }
    void calheight(int *r,int *sa,int n){
        for(int i = 1; i <= n; i++)Rank[sa[i]] = i;
        int j,k = 0;
        for(int i = 0; i < n; height[Rank[i++]] = k){
            for(k?k--:0,j = sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);
        }
    }
    int dp[MAXN][20];
    void RMQ(){
        for(int i = 1; i <= n; i++){
            dp[i][0] = height[i];
        }
        for(int i = 1; i < 20; 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 getnum(int x,int y){
        x = Rank[x];
        y = Rank[y];
        if(x > y)swap(x,y);
        x += 1;
        int k = (int)((log(y - x + 1) * 1.0) / log(2.0));
        return min(dp[x][k],dp[y - (1<<k) + 1][k]);
    }
    void solve(){
        int ans = 1;
        for(int i = 1; i < n; i++){
            for(int j = 0; j + i < n; j += i){
                int ret = getnum(j,j+i);
                int t = ret / i + 1;// behind r[i] can repeat t times
                int tp = j - (i - ret % i);
                if(tp >= 0 && (ret % i != 0) && getnum(tp,tp+i) >= ret){
                    t ++;
                }
                ans = max(t,ans);
            }
        }
        printf("%d
    ",ans);
    }
    int main(){
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d",&n);
            getchar();
            for(int i = 0; i < n; i++){
                scanf("%c",&s[i]);
                r[i] = s[i];
                getchar();
            }
            r[n] = 0;
            da(r,sa,n+1,128);
            calheight(r,sa,n);
            RMQ();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    linux资源监控命令详解
    c语言入门教程 / c语言入门经典书籍
    Hive存储过程实现-hpsql
    Hive集成mysql数据库
    Hive安装与配置
    Hbase shell操作总结(2)
    Hbase shell操作总结(1)
    Hbase 原理介绍
    Hbase的安装与配置
    Zookeeper工作原理(详细)
  • 原文地址:https://www.cnblogs.com/sweat123/p/5627892.html
Copyright © 2020-2023  润新知