给定一个字符串,求重复次数最多的连续重复子串。
http://www.spoj.com/problems/REPEATS/
枚举可能的循环节长度,不满足单调性,所以不能二分。
每个长度如果可以,一定会选到相邻的L个,于是找到0,L,2*L等等连续的两个,因为间隔L的两个一定是对应位置(画图理解),
找有没有满足s[L*i]== s[L*(i+1)]…每次(n/L)的复杂度,算起来 O(n/1+n/2+n/3+……+n/n)=O(nlogn)。
对于每个,往前找到最大前缀,往后找到最大后缀,加起来就是总长度S S/L+1为个数,如果S不够L长度相当于不符合条件,就是一个也没什么问题咯。
后缀:后缀数组求出后,求这两个位置的(rank【】)之间的所有height最小值(st可搞)
前缀:怎么办???把字符串反过来QAQ
附了几个可能wa的地方,比如1个字母特判。。
/*
枚举可能的循环节长度,不满足单调性,所以不能二分。
每个长度如果可以,一定会选到相邻的L个,于是找到0,L,2*L等等连续的两个,因为间隔L的两个一定是对应位置(画图理解),
找有没有满足s[L*i]== s[L*(i+1)]...每次(n/L)的复杂度,算起来 O(n/1+n/2+n/3+……+n/n)=O(nlogn)。
对于每个,往前找到最大前缀,往后找到最大后缀,加起来就是总长度S S/L+1为个数,如果S不够L长度相当于不符合条件,就是一个也没什么问题咯。
后缀:后缀数组求出后,求这两个位置的(rank【】)之间的所有height最小值(st可搞)
前缀:怎么办???把字符串反过来QAQ
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 50010;
int n,ans;
char a[maxn],ab[maxn];
typedef pair<char,int> pii;
int A[maxn],B[maxn],Ab[maxn],Bb[maxn];
int realrank[maxn],k,kb,realrankb[maxn];
pii st[maxn],stb[maxn];
int s[maxn][2],sb[maxn][2];
int h[maxn],hb[maxn];
int C[maxn],D[maxn],Cb[maxn],Db[maxn];
int stmin[maxn][20],stminb[maxn][20];
char ss[2];
void init(){
for(int i = 1; i <= n ; i++){
scanf("%s",ss);
a[i] = ss[0];
}
for(int i = 1; i <= n ; i++){
ab[i] = a[n-i+1];
}
for(int i = 1; i <= n ; i++){
st[i] = make_pair(a[i],i);
stb[i]= make_pair(ab[i],i);
}
sort(st+1,st+1+n);
sort(stb,stb+1+n);
k = realrank[st[1].second] = 1;
kb = realrankb[stb[1].second] = 1;
for(int i = 2; i <= n ; i++){
if(st[i].first != st[i-1].first)
k += 1;
if(stb[i].first != stb[i-1].first)
kb += 1;
realrank[st[i].second] = k;
realrankb[stb[i].second] = kb;
}
}
void suffix_array(){
for(int i = 1; i <= n ; i *= 2){
for(int j = 0 ; j <= n ; j++)
A[j] = B[j] = Ab[j] = Bb[j] = 0;
for(int j = 1; j <= n ; j++){
A[s[j][0] = realrank[j]]++;
Ab[sb[j][0] = realrankb[j]]++;
if(j+i <= n){
s[j][1] = realrank[j+i];
sb[j][1] = realrankb[j+i];
}
else s[j][1] = sb[j][1] = 0;
B[s[j][1]]++;
Bb[sb[j][1]]++;
}
for(int j = 1; j <= n ;j++)
A[j] += A[j-1],B[j] += B[j-1],Ab[j] += Ab[j-1],Bb[j] += Bb[j-1];
for(int j = n ; j >= 1; j--){
C[B[s[j][1]]] = j;
Cb[Bb[sb[j][1]]] = j;
B[s[j][1]]--;
Bb[sb[j][1]]--;
}
for(int j = n ; j >=1; j--){
D[A[s[C[j]][0]]] = C[j];
Db[Ab[sb[Cb[j]][0]]] = Cb[j];
A[s[C[j]][0]]--;
Ab[sb[Cb[j]][0]]--;
}
k = realrank[D[1]] = 1;
kb = realrankb[Db[1]] = 1;
for(int j = 2 ; j <= n ; j++){
if(s[D[j]][0] != s[D[j-1]][0] ||s[D[j]][1] != s[D[j-1]][1])
k++;
realrank[D[j]] = k;
if(sb[Db[j]][0] != sb[Db[j-1]][0] ||sb[Db[j]][1] != sb[Db[j-1]][1])
kb++;
realrankb[Db[j]] = kb;
}
}
}
void gethigh(){
int pre = 0,j;
for(int i = 1; i <= n ; i++){
if(pre) pre--;
j = D[realrank[i]-1];
while(i+pre <= n && j + pre <= n && a[i+pre] == a[j+pre])
pre++;
h[realrank[i]] = pre;
}
pre = 0;
for(int i = 1; i <= n ; i++){
if(pre) pre--;
j = Db[realrankb[i]-1];
while(i+pre <= n && j + pre <= n && ab[i+pre] == ab[j+pre])
pre++;
hb[realrankb[i]] = pre;
}
}
int qur(int l,int r){
if(l > r) swap(l,r);
l+=1;
int len = r-l+1;
int k = (int)floor(log2(len));
return min(stmin[l][k],stmin[r-(1<<k)+1][k]);
}
int qurb(int l,int r){
// printf("l = %d r = %d\n",l,r);
if(l > r) swap(l,r);
l += 1;
int len = r-l+1;
int k = (int)floor(log2(len));
return min(stminb[l][k],stminb[r-(1<<k)+1][k]);
}
void sov(){
ans = 1;
for(int L = 1; L <= n; L++){
//cout <<"L = "<<L<<endl;
for(int j = L+1; j <= n ;j += L){
int cnt = 0;
if(a[j] == a[j-L]){
//printf("j = %d\n",j);
cnt += qur(realrank[j],realrank[j-L]);
//printf("cnt = %d\n",cnt);
//cout <<"realrank = "<<realrankb[1]<<endl;
cnt += qurb(realrankb[n-j+1],realrankb[n-(j-L)+1]);
//printf("cnt = %d\n",cnt);
ans = max(ans,(cnt-1)/L+1);
}
}
}
printf("%d\n",ans);
}
void getst(){
for(int i = 1 ; i <= n ; i++){
stmin[i][0] = h[i];
stminb[i][0] = hb[i];
}
for(int i = n ; i >= 1; i--){
for(int j = 1; (i+(1<<j)-1) <= n ;j++){
stmin[i][j] = min(stmin[i][j-1],stmin[i+(1<<(j-1))][j-1]);
stminb[i][j] = min(stminb[i][j-1],stminb[i+(1<<(j-1))][j-1]);
}
}
}
int main(){
int T;
scanf("%d",&T);
for(int i = 1; i <= T ; i++){
scanf("%d",&n);
if(n == 1){
scanf("%s",ss);
printf("1\n");
continue;
}
init();
suffix_array();
gethigh();
getst();
sov();
}
}
/*
100
4
a
a
a
a
3
a
b
b
1
a
2
a
a
2
a
b
*/