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\n",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;
}
时间: 2024-08-10 11:31:00

spoj687 后缀数组重复次数最多的连续重复子串的相关文章

POJ - 3693 Maximum repetition substring(后缀数组求重复次数最多的连续重复子串)

Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1. Given a

【POJ 3693】Maximum repetition substring 重复次数最多的连续重复子串

后缀数组的论文里的例题,论文里的题解并没有看懂,,, 求一个重复次数最多的连续重复子串,又因为要找最靠前的,所以扫的时候记录最大的重复次数为$ans$,扫完后再后从头暴力扫到尾找重复次数为$ans$的第一个子串的开头,break输出就可以了 #include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1000

Maximum repetition substring POJ - 3693(重复次数最多的连续重复子串)

这题和SPOJ - REPEATS 一样  代码改一下就好了 这个题是求这个重复子串,还得保证字典序最小 巧妙运用sa 看这个 https://blog.csdn.net/queuelovestack/article/details/53035903 很清晰 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include&l

poj 3693 后缀数组求重复次数最多的连续重复子串

#include<iostream> #include<cstring> #include<set> #include<map> #include<cmath> #include<stack> #include<queue> #include<deque> #include<list> #include<algorithm> #include<stdio.h> #includ

【poj3693-重复次数最多的连续重复子串】后缀数组

题意:给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个). 例如ccabcabc,答案就是abcabc 一开始没想清楚,结果调了好久. 对于当前的L,i,i+1,x=s[i*L],y=s[(i+1)*L],找前找后,知道了最早能匹配到t0,最晚能匹配到t1,因为不知道当前的起始点是真正循环节的第几个点,所以我们要往前找L个点看看它们是不是真正的起始点. 细节就看代码吧: #include<cstdio> #include<cstdlib> #

POJ 3693 Maximum repetition substring (寻找重复次数最多的连续子串)

Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9083   Accepted: 2782 Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same conse

poj 3693 Maximum repetition substring 重复次数最多的连续子串

题目链接 题意 对于任意的字符串,定义它的 重复次数 为:它最多可被划分成的完全相同的子串个数.例如:ababab 的重复次数为3,ababa 的重复次数为1. 现给定一字符串,求它的一个子串,其重复次数取到最大值,且字典序取到最小值. 思路 参考 hzwer. 首先,重复次数显然至少为\(1\),所以下面只考虑重复次数\(\geq 2\)的情况. 首先枚举子串长度\(L\).对于长度为\(L\)的子串,其重复次数至少为\(2\),意味着它的其中两个重复部分必为\(s[0],s[L],s[2L]

POJ 题目 3693 Maximum repetition substring(后缀数组+RMQ+枚举求最小字典序的重复次数最多的子串)

Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8067   Accepted: 2463 Description The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same conse

寻找数组中重复次数最多的数

#include<iostream> #include<map> using namespace std; int helper(const int a[],const int n) { map<int,int> m; for(int i = 0;i<n;i++) m[a[i]]++; map<int,int>::iterator comp = m.begin(); for( map<int,int>::iterator it = comp