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: 4since a (4, 3)-repeat is found starting at the 5th character of the input string.
题目大意: 求给出的字符串中重复次数最多的连续重复子串。
解题思路:先枚举长度l, 然后求长度为l的子串最多能里连续出现几次。首先连续出现1次是肯定可以的,所以这里指考虑至少2次的情况。假设在原字符串中连续出现2次,记这个子字符串为s,那么肯定包括了r[0], r[l,], r[l * 2], r[l * 3]......中的某个相邻的两个。所以只需要看字符r[l * i] 和r[l *(i + 1)] 往前和往后各能匹配多远,记这个总长度为k, 那么这里连续出现了k/l + 1次。最后看最大值是多少即可。
在对求见查询的时候,需要用到RMQ算法。
因为是正好写到了这个题,才去现学的RMQ,所以,刚开始写的有些偏差,一直RE。。。
/*
@Author: Top_Spirit
@Language: C++
*/
#include <bits/stdc++.h>
using namespace std ;
typedef unsigned long long ull ;
typedef long long ll ;
const int Maxn = 5e4 + 10 ;
const int INF = 0x3f3f3f3f ;
const ull seed = 133 ;
const double PI = acos(-1.0) ;
int sa[Maxn],Rank[Maxn],height[Maxn];
int wa[Maxn],wb[Maxn],Ws[Maxn],wv[Maxn];
char str[Maxn];
int n ;
int cmp (int *r,int a,int b,int l){
return r[a] == r[b] && r[a + l] == r[b + l];
}
void get_sa (int *r,int n,int m){
int i , j, p , *x = wa,*y = wb,*t;
for (i = 0; i < m; i++) Ws[i] = 0;
for (i = 0; i < n; i++) Ws[x[i] = r[i]]++;
for (i = 1; i < m; i++) Ws[i] += Ws[i - 1];
for (i = n - 1; i >= 0; i--) sa[--Ws[x[i]]] = i;
for (j = 1, p = 1; p < n; j *= 2, m = p){
for (p = 0,i = n - j; i < n; i++) y[p++] = i;
for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j ;
for (i = 0; i < n; i++) wv[i] = x[y[i]];
for (i = 0; i < m; i++) Ws[i] = 0;
for (i = 0; i < n; i++) Ws[wv[i]]++;
for (i = 0; i < m; i++) Ws[i] += Ws[i - 1];
for (i = n - 1; i >= 0; i--) sa[--Ws[wv[i]]] = y[i];
for (t = x, x = y, y = t,p = 1, x[sa[0]] = 0, i = 1; i < n ; i++){
x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
}
}
}
void get_height(int *r,int n){
int k = 0, j ;
for (int i = 1 ;i <= n; i++) Rank[sa[i]] = i;
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 a[Maxn] ;
int dp[Maxn][20] ;
void rmqInit(){
for (int i = 1; i <= n; i++) dp[i][0] = height[i] ;
int m=(int)(log(n*1.0)/log(2.0));
for (int j = 1; j <= m; j++){
for (int i = 1; i + (1 << j) - 1 <= n; i++){
dp[i][j] = min(dp[i][j - 1], dp[i + (1 << j - 1)][j - 1]) ;
}
}
}
int getRmq(int x, int y){
int l = Rank[x], r = Rank[y] ;
if (l > r) swap(l ,r) ;
l++ ;
int k=int(log(r-l+1.0)/log(2.0));
return min(dp[l][k],dp[r -(1 << k) + 1][k]);
}
int main (){
int T ;
scanf("%d", &T) ;
while (T--){
scanf("%d", &n) ;
for (int i = 0; i < n; i++){
scanf("%s", str) ;
a[i] = str[0] ;
}
// a[n] = 0 ;
get_sa(a, n + 1, 300) ;
get_height(a, n) ;
rmqInit() ;
int Max = 0 ;
for (int i = 1; i <= n; i++){
for (int j = 0; j + i < n; j += i){
int tmp = getRmq(j, j + i), k = j - (i - tmp % i ) ;
tmp = tmp / i + 1 ;
if (k >= 0 && getRmq(k, k + i) >= i) tmp++;
Max = max(Max, tmp) ;
}
}
cout << Max << endl ;
}
return 0;
}