POJ 3261 字符串上的k次覆盖问题
2015-04-03 02:16
211 查看
题目大意:
给定一个数组,求一个最大的长度的子串至少出现过k次
一个子串出现多次,也就是说必然存在2个子串间的前缀长度为所求的值
通过二分答案,通过线性扫一遍,去判断出现次数,也就是说每次遇见一个height[i] , 出现次数就加1,否则重置为1
给定一个数组,求一个最大的长度的子串至少出现过k次
一个子串出现多次,也就是说必然存在2个子串间的前缀长度为所求的值
通过二分答案,通过线性扫一遍,去判断出现次数,也就是说每次遇见一个height[i] , 出现次数就加1,否则重置为1
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int N = 20010; int rank , sa , height ; int wa , wb , wsf , wv ; int a ; int cmp(int *r , int a , int b , int l) { return r[a]==r[b] && r[a+l]==r[b+l]; } void getSa(int *r , int *sa , int n , int m) { int i,j,p; int *x=wa , *y=wb , *t; for(i=0 ; i<m ; i++) wsf[i]=0; for(i=0 ; i<n ; i++) wsf[x[i]=r[i]]++; for(i=1 ; i<m ; i++) wsf[i] += wsf[i-1]; for(i=n-1 ; i>=0 ; i--) sa[--wsf[x[i]]]=i; p=1; for(j=1 ; p<n ; j*=2 , m=p){ for(p=0 , i=n-j ; i<n ; i++) y[p++]=i; for(i=0 ; i<n ; i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0 ; i<n ; i++) wv[i]=x[y[i]]; for(i=0 ; i<m ; i++) wsf[i]=0; for(i=0 ; i<n ; i++) wsf[wv[i]]++; for(i=1 ; i<m ; i++) wsf[i]+=wsf[i-1]; for(i=n-1 ; i>=0 ; i--) sa[--wsf[wv[i]]]=y[i]; t=x,x=y,y=t; x[sa[0]]=0; for(p=1 , i=1 ; i<n ; i++) x[sa[i]] = cmp(y , sa[i-1] , sa[i] , j)?p-1:p++; } return ; } void getHeight(int *r , int *sa , int n) { for(int i=1 ; i<=n ; i++) rank[sa[i]]=i; int k=0; int j; for(int i=0 ; i<n ; height[rank[i++]]=k) for(k?k--:0 , j=sa[rank[i]-1] ; r[i+k]==r[j+k] ; k++); return; } bool check(int m , int n , int k) { int cnt=1; for(int i=1 ; i<=n ; i++){ if(height[i]>=m){ cnt++; // cout<<"here: "<<m<<" "<<sa[i]<<" "<<sa[i-1]<<endl; if(cnt>=k) return true; } else {cnt=1;if(cnt>=k) return true;} } return false; } int main() { // freopen("a.in" , "r" , stdin); int n,k; while(~scanf("%d%d" , &n , &k)) { int maxn =0 ; for(int i=0 ; i<n ; i++){ scanf("%d" , a+i); a[i]++; maxn = max(maxn , a[i]); } a =0; getSa(a , sa , n+1 , maxn+1); getHeight(a , sa , n); int l=0 , r=n , ans=0; while(l <= r){ int m=(l+r)>>1; if(check(m,n,k)){ ans = m; l=m+1; }else r=m-1; } printf("%d\n" , ans); } return 0; }
相关文章推荐
- 出现k次以上重复的最长子串 poj 3261
- poj 2226 还是最小点覆盖的匹配问题
- poj 1436 Horizontally Visible Segments(线段树成段覆盖问题+简单hash),好题,覆盖问题想法较难
- poj 3711: 字符串移位包含问题
- POJ 3074 SUKODU [Dancing Links DLX精准覆盖问题]
- poj 3261 Milk Patterns 最长的出现最少k次的重复(可重叠)子串 后缀数组
- 最小路径覆盖问题poj2594&&poj1422(匈牙利解法)
- 关于字符串覆盖问题的解答。
- poj 3020 二分图 最大匹配(最小边覆盖问题)
- poj 1089 贪心之区间覆盖问题
- poj 3261 求可重叠k次最长重复子串
- POJ 3261 字符串
- POJ_3740——精确覆盖问题,DLX模版
- poj 1981 Circle and Points(圆覆盖点问题)
- poj 2125 最小割解决 "最小点权覆盖问题" +输出解(割边集)
- POJ 2185 (字符串最小覆盖)
- 字符串 后缀数组(可重叠的k 次最长重复子串)poj 3261
- POJ 3261 Milk Patterns (离散化+后缀数组 可重叠k次最长重复子串)
- POJ 2376 Cleaning Shifts 区间覆盖问题
- poj1106-Transmitters 几何覆盖问题