P7180 [BOI2004] REPEATS
P7180 [BOI2004] REPEATS
题意:给定字符串,求重复次数最多的连续重复子串。
考虑枚举这个子串的长度
考虑优化,其实我们并不需要枚举所有的
lcp 和 lcs(反串 lcp)可使用后缀数组求解。
复杂度为
//P7180
#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
int t, n, a[N], lg2[N];
int sa[N], rk[N], cn[N], pr[N], he[N];
int st[N][20], stt[N][20];
int saa[N], rkk[N], hee[N];
void initial(){
memset(sa, 0, sizeof(sa));
memset(rk, 0, sizeof(rk));
memset(cn, 0, sizeof(cn));
memset(pr, 0, sizeof(pr));
memset(he, 0, sizeof(he));
}
void suftech(){
int m = 26;
for(int i = 1; i <= n; ++ i){
rk[i] = a[i];
++ cn[rk[i]];
}
for(int i = 2; i <= m; ++ i){
cn[i] += cn[i-1];
}
for(int i = n; i >= 1; -- i){
sa[cn[rk[i]]--] = i;
}
for(int k = 1; k <= n; k <<= 1){
int tot = 0;
for(int i = n - k + 1; i <= n; ++ i){
pr[++tot] = i;
}
for(int i = 1; i <= n; ++ i){
if(sa[i] > k){
pr[++tot] = sa[i] - k;
}
}
for(int i = 1; i <= m; ++ i){
cn[i] = 0;
}
for(int i = 1; i <= n; ++ i){
++ cn[rk[i]];
}
for(int i = 2; i <= m; ++ i){
cn[i] += cn[i-1];
}
for(int i = n; i >= 1; -- i){
sa[cn[rk[pr[i]]]--] = pr[i];
pr[i] = 0;
}
swap(rk, pr);
tot = 1;
rk[sa[1]] = 1;
for(int i = 2; i <= n; ++ i){
if(pr[sa[i]] == pr[sa[i-1]] && pr[sa[i]+k] == pr[sa[i-1]+k]){
rk[sa[i]] = tot;
} else {
rk[sa[i]] = ++ tot;
}
}
if(tot == n){
break;
}
m = tot;
}
int k = 0;
for(int i = 1; i <= n; ++ i){
if(rk[i] == 1){
he[rk[i]] = 0;
}
if(k){
-- k;
}
int j = sa[rk[i]-1];
while(i+k <= n && j+k <= n && a[i+k] == a[j+k]){
++ k;
}
he[rk[i]] = k;
}
for(int i = 1; i <= n; ++ i){
st[i][0] = he[i];
}
for(int i = 1; i <= lg2[n]; ++ i){
for(int j = 1; j + (1<<i) - 1 <= n; ++ j){
st[j][i] = min(st[j][i-1], st[j+(1<<(i-1))][i-1]);
}
}
}
int ask(int l, int r){
if(l > r){
swap(l, r);
}
++ l;
int k = lg2[r - l + 1];
return min(st[l][k], st[r-(1<<k)+1][k]);
}
int askk(int l, int r){
if(l > r){
swap(l, r);
}
++ l;
int k = lg2[r - l + 1];
return min(stt[l][k], stt[r-(1<<k)+1][k]);
}
int main(){
lg2[0] = -1;
for(int i = 1; i <= 50000; ++ i){
lg2[i] = lg2[i>>1] + 1;
}
scanf("%d", &n);
int ans = 0, lee, stp;
for(int i = 1; i <= n; ++ i){
static char ch[5];
scanf("%s", ch);
a[i] = ch[0] - 'a' + 1;
}
initial();
suftech();
reverse(a + 1, a + n + 1);
memcpy(stt, st, sizeof(st));
memcpy(saa, sa, sizeof(sa));
memcpy(rkk, rk, sizeof(rk));
memcpy(hee, he, sizeof(he));
initial();
suftech();
for(int len = 1; len <= n; ++ len){
for(int st = 1; st + len - 1 <= n; st += len){
int r = st + len + askk(rkk[st], rkk[st+len]) - 1;
int l = st - 1 - ask(rk[n-(st+len-1)+1], rk[n-(st-1)+1]) + 1;
if(ans < (r-l+1) / len){
ans = (r-l+1) / len;
lee = len;
stp = l;
}
}
}
printf("%d\n%d\n%d\n", ans, lee, stp);
return 0;
}