傳送門:BZOJ1717
解題思路
先把正解說一說:單調隊列或者二分
然後麼。。爲什麼我寫的這麼長?!
是羅穗騫的論文題嘛……就當給後綴數組練手吧
可重疊k次重複字串
YM代碼
#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define red(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
inline int read() {
int x = 0;
char ch = getchar();
while(ch < '0' || ch > '9') ch = getchar();
while(ch >= '0' || ch <= '9') {
x *= 10; x += ch - '0';
ch = getchar();
}
return x;
}
const int N = 20005;
int n, m, k, p, q, tot = 0;
int a[N], num[N], hash[N], v[N], h[N], height[N], sa[2][N], rank[2][N];
int find(int x) {
int l = 1, r = tot, ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if (hash[mid] <= x) ans = mid, l = mid + 1;
else r = mid - 1;
}
return ans;
}
bool jud(int x) {
int tmp = 0;
rep(i, 1, n) {
if (height[i] >= x) {
tmp++;
if (tmp == m-1) return 1;
}else tmp = 0;
}
return 0;
}
void getans() {
k = 0;
rep(i, 1, n) {
if (rank[p][i] == 1) h[i] = 0;
else {
int j = sa[p][rank[p][i]-1];
while(a[i+k] == a[j+k]) k++;
h[i] = k;
if (k > 0) k--;
}
}
rep(i, 1, n) height[rank[p][i]] = h[i];
int l = 1, r = n, ans = 0;
while(l <= r) {
int mid = (l + r) >> 1;
if (jud(mid)) ans = mid, l = mid + 1;
else r = mid - 1;
}
printf("%d\n", ans);
}
void calsa(int sa[N], int rk[N], int SA[N], int RK[N]) {
rep(i, 1, n) v[rk[sa[i]]] = i;
red(i, n, 1) if (sa[i] > k) SA[v[rk[sa[i]-k]]--] = sa[i] - k;
rep(i, n-k+1, n) SA[v[rk[i]]--] = i;
rep(i, 1, n) RK[SA[i]] = RK[SA[i-1]] + (rk[SA[i]] != rk[SA[i-1]] || rk[SA[i]+k] != rk[SA[i-1]+k]);
}
void work() {
p = 0, q = 1; a[0] = -1;
rep(i, 1, n) v[a[i]]++;
rep(i, 1, n) v[i] += v[i-1];
rep(i, 1, n) sa[p][v[a[i]]--] = i;
rep(i, 1, n)
if(a[sa[p][i]] != a[sa[p][i-1]])
rank[p][sa[p][i]] = rank[p][sa[p][i-1]] + 1;
else rank[p][sa[p][i]] = rank[p][sa[p][i-1]];
k = 1;
while(k < n) {
calsa(sa[p], rank[p], sa[q], rank[q]);
p^=1; q^=1; k<<=1;
}
getans();
}
int main() {
scanf("%d%d", &n, &m);
rep(i, 1, n) {
scanf("%d", &a[i]);
num[i] = a[i];
}
sort(num + 1, num + n + 1);
hash[++tot] = num[1];
rep(i, 2, n) {
if (num[i] != num[i-1])
hash[++tot] = num[i];
}
rep(i, 1, n) a[i] = find(a[i]);
work();
return 0;
}
尾聲
好長好長…好長好長…
真的不想…一直做碼題~~