(Relax 后缀数组1.2)POJ 3261 Milk Patterns(求一个长度为n的整数序列中,至少出现k次的子序列的最长的长度)
2013-11-25 10:04
615 查看
【题意】
给定一个长度为n的整数序列,求其中至少出现k次的子序列长度最长为多长
【输入】
第一行n和k
接下来n个数字描述序列
【输出】
一个数字,表示至少出现过k次的子序列最长长度
也是09年论文《后缀数组——处理字符串的有力工具》上的例题
不过不同之处是二分答案之时,判断方式是一组中是否有k个后缀
给定一个长度为n的整数序列,求其中至少出现k次的子序列长度最长为多长
【输入】
第一行n和k
接下来n个数字描述序列
【输出】
一个数字,表示至少出现过k次的子序列最长长度
也是09年论文《后缀数组——处理字符串的有力工具》上的例题
不过不同之处是二分答案之时,判断方式是一组中是否有k个后缀
/* * POJ_3261.cpp * * Created on: 2013年11月25日 * Author: Administrator */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int maxn = 20010; struct number{ int x; int pos; }num[maxn]; struct node{ int now; int next; }d[maxn]; int val[maxn][2]; int c[maxn]; int rank[maxn]; int sa[maxn]; int pos[maxn]; int x[maxn]; int n; int k; int h[maxn]; int height[maxn]; bool cmp(const number& a,const number& b){ return a.x < b.x; } void add_value(int u, int v, int i) { d[i].next = c[u]; c[u] = i; d[i].now = v; } void radix_sort(int l, int r) { for(int k = 1 ; k >= 0 ; --k){ memset(c, 0, sizeof(c)); for(int i = r ; i >= l ; --i){ add_value(val[pos[i]][k], pos[i], i); } int t = 0; for(int i = 0 ; i <= 20000 ; ++i){ for (int j = c[i]; j; j = d[j].next){ pos[++t] = d[j].now; } } } int t = 0; for(int i = 1 ; i <= n ; ++i){ if (val[pos[i]][0] != val[pos[i - 1]][0]|| val[pos[i]][1] != val[pos[i - 1]][1]){ t++; } rank[pos[i]] = t; } } bool exist(int len) { int now = 0; int s = 0; for(int i = 1 ; i <= n ; ++i){//枚举名次数组... if (height[i] < len) { s = max(s,now);//结束当前组 now = 1;//now恢复为1 } else { now++; } } s = max(s,now); if(s >= k){ return 1; } return 0; } void get_suffix_array() { int t = 1; while (t / 2 <= n) { for(int i = 1 ; i <= n ; ++i){ val[i][0] = rank[i]; val[i][1] = (((i + t / 2 <= n) ? rank[i + t / 2] : 0)); pos[i] = i; } radix_sort(1, n); t *= 2; } for(int i = 1 ; i <= n ; ++i){ sa[rank[i]] = i; } } void get_common_prefix() { memset(h, 0, sizeof(h)); for(int i = 1 ; i <= n ; ++i){ if (rank[i] == 1){ h[i] = 0; } else { int now = 0; if (i > 1 && h[i - 1] > 1){ now = h[i - 1] - 1; } while (now + i <= n && now + sa[rank[i] - 1] <= n&& x[now + i] == x[now + sa[rank[i] - 1]]){ now++; } h[i] = now; } } for(int i = 1 ; i <= n ; ++i){ height[rank[i]] = h[i]; } } int binary_search(int l, int r) { while (l <= r) { int mid = (l + r) / 2; if (exist(mid)){ l = mid + 1; }else{ r = mid - 1; } } return r; } void discretization(){//分组 sort(num+1,num+1+n,cmp); int t = 0; num[0].x = -1; for(int i = 1 ; i <= n ; ++i){ if(num[i].x != num[i-1].x){ t++; } rank[num[i].pos] = t; } } void solve() { discretization(); get_suffix_array(); get_common_prefix(); int ans = binary_search(0,n); printf("%d\n",ans); } int main(){ while(scanf("%d%d",&n,&k)!=EOF){ int i; for(i = 1 ; i <= n ; ++i){ scanf("%d",&x[i]); } for(i = 1 ; i <= n ; ++i){ num[i].x = x[i]; num[i].pos = i; } solve(); } return 0; }
相关文章推荐
- POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次
- POJ 题目3261 Milk Patterns(后缀数组求最长重叠至少k次的子串长度)
- poj 3261 Milk Patterns (后缀数组 至少出现k次的可重叠最长重复子串)
- POJ 3261 Milk Patterns(后缀数组 重复出现K次字串的长度)
- poj 3261 Milk Patterns(最长至少k次重复子串,后缀数组基础题)
- poj 3882 后缀数组 求一个串至少出现k次的最长重复子串的长度
- POJ 3261 - Milk Patterns (可重叠的k次最长重复子串 后缀数组)
- POJ 3261 Milk Patterns(后缀数组 + 可重叠最长重复子串次数大于k)
- PKU 3261(求最长的至少出现k次的子串,后缀数组+二分枚举)
- poj 3261 Milk Patterns 最长的出现最少k次的重复(可重叠)子串 后缀数组
- POJ 3261 Milk Patterns 最长出现k次的子串长度(后缀数组)
- 【后缀数组 重叠重复字串个数大于k的最长长度】POJ - 3261 Milk Patterns
- POJ 3261 Milk Patterns (后缀数组,求可重叠的k次最长重复子串)
- poj 3261 Milk Patterns 后缀数组 最长重复子串
- poj 3261 Milk Patterns(后缀数组-最长重复子串)
- POJ 3261 Milk Patterns【后缀数组】可重叠的k次最长子串
- POJ-3261 Milk Patterns (后缀数组 最长k次重复子串)
- POJ 3261 - Milk Patterns 求指定重复次数的最长子串,后缀数组+二分 or 线段树
- POJ 3261 Milk Patterns (离散化+后缀数组 k次最长重复子串(可重叠))
- POJ - 3261 Milk Patterns (后缀数组求可重叠的 k 次最长重复子串)