Longest Repeated subsequence
HDU - 2890
Write a program that takes a sequence of number and returns length of the longest repeated
subsequence. A repeated subsequence which repeats identically at least K times without overlaps.
For example 1 2 3 1 2 3 2 3 1 repeats 2 3 for three times.
subsequence. A repeated subsequence which repeats identically at least K times without overlaps.
For example 1 2 3 1 2 3 2 3 1 repeats 2 3 for three times.
Line 2: Two space-separated integers: N and K (1 <= n <= 50000), (2 <= k <= n)
Lines 3..N+2: N integers, one per line. The integer is between 0 and 10^9.
It is guaranteed that at least one subsequence is repeated at least K times.
1 8 2 1 2 3 2 3 2 3 1
2 2 3
My Solution
题意:给出一个序列,要求找出出现过至少m次的最长(连续)子序列,求其最长长度和具体字典序最小的序列,且不能有重叠。 后缀数组+二分+贪心
先离散化,然后跑出后缀数组sa和height数组,然后二分答案,检查的时候,维护height[i] > mid 的sa[i]值及个数,日光个数大于等于m, 则把这段区间的sa[i],排序,然后从小的开始贪,相邻的2个,如果间隔小于mid,则去掉大的比去掉小的sa[i]更好,然后讨论下一个, 最后判断剩余的sa[i]的两两间隔不小于mid的sa[i]的个数大于等于m,则这就是答案,要求字典序最小所以check的时候碰到第一个满足的答案就可以return了。 复杂度 O(nlognlogn)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 5e4 + 8;
int sa[maxn], height[maxn];
int _rank[maxn], t1[maxn], t2[maxn], c[maxn];
int s[maxn];
inline void get_sa(const int &n, int m)
{
int i, k, *x = t1, *y = t2, p, j;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) ++ c[x[i] = s[i]];
for(i = 1; i < m; i++) c[i] += c[i - 1];
for(i = n - 1; i >= 0; i--) sa[-- c[x[i]]] = i;
for(k = 1; k <= n; k <<= 1){
p = 0;
for(i = n - k; i < n; i++) y[p ++] = i;
for(i = 0; i < n; i++) if(sa[i] >= k) y[p ++] = sa[i] - k;
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) ++ c[x[y[i]]];
for(i = 1; i < m; i++) c[i] += c[i - 1];
for(i = n - 1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
swap(x, y), p = 1, x[sa[0]] = 0;
for(i = 1; i < n; i++)
x[sa[i]] = (y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]) ? p - 1 : p ++;
if(p >= n) break;
m = p;
}
k = 0;
for(i = 0; i < n; i++) _rank[sa[i]] = i;
for(i = 0; i < n; i++){
if(k) --k; if(!_rank[i]) continue;
j = sa[_rank[i] - 1];
while(s[i + k] == s[j + k]) k++;
height[_rank[i]] = k;
}
}
int val[maxn];
inline void print(const int &n)
{
for(int i = 1; i <= n; i++){
//cout << i << " : " << height[i] << " " << sa[i] << endl;
for(int j = sa[i]; j < n; j++){
cout << val[j];
}
cout << endl;
}
cout << endl;
}
map<int, int> Ind;
vector<int> vec;
int start, t, m, n, cnt;
inline bool check(const int &x)
{
cnt = 1; t = 1; vec.push_back(sa[1]);
for(int i = 2, j, sz, res; i <= n; i++){
if(height[i] >= x) {cnt++; vec.push_back(sa[i]);}
else{cnt = 1; t = i; vec.clear(); vec.push_back(sa[i]);}
if(cnt >= m){
if(i == n || height[i+1] < x){
sort(vec.begin(), vec.end());
sz = vec.size(); res = vec[0];
for(j = 1; j < sz; j++){
if(vec[j] - res < x) cnt--;
else res = vec[j];
}
if(cnt >= m){ start = t; return true;}
}
}
}
return false;
}
int main()
{
#ifdef LOCAL
freopen("8.in", "r", stdin);
//freopen("8.out", "w", stdout);
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);
int T, sz, i, ansa, ansb, l, r, mid;
cin >> T;
while(T--){
cin >> n >> m;
vec.clear(); Ind.clear(); memset(s, 0, sizeof s);
for(i = 0; i < n; i++){
cin >> val[i];
vec.push_back(val[i]);
}
if(m == 1){cout << n << "\n"; for(i = 0; i < n; i++) cout << val[i] << "\n"; if(T) cout << "\n"; continue;}
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
sz = vec.size();
for(i = 0; i < sz; i++){
Ind[vec[i]] = i + 1;
//cout << vec[i] << " " << i + 1 << endl;
}
for(i = 0; i < n; i++) s[i] = Ind[val[i]];
get_sa(n+1, sz+8);
//print(n);
ansa = ansb = 0; l = 0, r = n + 1;
while(l + 1 < r){
mid = (l + r) >> 1; vec.clear();
if(check(mid)){ansa = mid; ansb = start; l = mid; }
else r = mid;
}
cout << ansa << "\n";
for(i = sa[ansb]; i < sa[ansb] + ansa; i++) cout << val[i] << "\n";
if(T) cout << "\n";
}
return 0;
}
Thank you ------from ProLights