poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列

 1 #include "stdio.h"
 2 #define maxn 20010
 3
 4 int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
 5 int rank[maxn],height[maxn];
 6 int r[maxn],sa[maxn],ans[maxn];
 7 int n,res,k;
 8
 9 int cmp(int *r,int a,int b,int l)
10 {
11     return r[a]==r[b]&&r[a+l]==r[b+l];
12 }
13
14 void da(int *r,int *sa,int n,int m)
15 {
16     int i,j,p,*x=wa,*y=wb,*t;
17     for(i=0; i<m; i++) ws[i]=0;
18     for(i=0; i<n; i++) ws[x[i]=r[i]]++;
19     for(i=1; i<m; i++) ws[i]+=ws[i-1];
20     for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
21     for(j=1,p=1; p<n; j*=2,m=p)
22     {
23
24         for(p=0,i=n-j; i<n; i++) y[p++]=i;
25         for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
26         for(i=0; i<n; i++) wv[i]=x[y[i]];
27         for(i=0; i<m; i++) ws[i]=0;
28         for(i=0; i<n; i++) ws[wv[i]]++;
29         for(i=1; i<m; i++) ws[i]+=ws[i-1];
30         for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
31         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
32             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
33     }
34     return;
35 }
36
37 void calheight(int *r,int *sa,int n)
38 {
39     int i,j,k=0;
40     for(i=1; i<=n; i++) rank[sa[i]]=i;
41     for(i=0; i<n; height[rank[i++]]=k)
42         for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
43     return;
44 }
45
46 bool calc(int x)        //x:length
47 {
48     int rec[maxn];
49     int nm=0;
50     for (int i=1;i<=n;i++)
51     {
52         if (height[i]<x)
53         {
54             nm++;
55             rec[nm]=i;
56         }
57     }
58     nm++;   rec[nm]=n+1;
59     for (int i=1;i<=nm;i++)
60     {
61         int tl=rec[i-1],tr=rec[i];
62         if (tr-tl>=k)      return true;
63     }
64     return false;
65 }
66
67 int main()
68 {
69     scanf("%d %d",&n,&k);
70     for (int i=0; i<n; i++)
71         scanf("%d",&r[i]);
72     r[n]=0;
73
74     da(r,sa,n+1,200);
75     calheight(r,sa,n);
76
77     //TODO: Please Code Here
78     int l=0,r=n,res=0;
79     while (r>=l)
80     {
81         int mid=(l+r)/2;
82         if (calc(mid))
83         {
84             if (mid>res)    res=mid;
85             l=mid+1;
86         }
87         else
88             r=mid-1;
89     }
90     printf("%d\n",res);
91     return 0;
92 }
时间: 2024-07-30 22:30:06

poj 3261 二分答案+后缀数组 求至少出现k次的最长重复子序列的相关文章

poj 1743 二分答案+后缀数组 求不重叠的最长重复子串

题意:给出一串序列,求最长的theme长度 (theme:完全重叠的子序列,如1 2 3和1 2 3  or  子序列中每个元素对应的差相等,如1 2 3和7 8 9) 要是没有差相等这个条件那就好办多了,直接裸题. 一开始想了个2B方法,后来发现真心2B啊蛤蛤蛤 1 for i=1 to 88 do 2 { 3 for j=1 to length 4 { 5 r2[j]=r[j]+i; 6 if (r2[j]>88) r2[i]-=88; 7 } 8 把新序列r2连接到原序列r的后面 9 pr

POJ - 3261 Milk Patterns (后缀数组求可重叠的 k 次最长重复子串)

Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular pattern

POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

Milk Patterns Description Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some r

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树)

[LuoguP4094] [HEOI2016] [TJOI2016]字符串(二分答案+后缀数组+ST表+主席树) 题面 给出一个长度为\(n\)的字符串\(s\),以及\(m\)组询问.每个询问是一个四元组\((a,b,c,d)\),问\(s[a,b]\)的所有子串和字符串\(s[c,d]\)的最长公共前缀长度的最大值. \(n,m \leq 10^5\) 分析 显然答案有单调性.首先我们二分答案\(mid\),考虑如何判定. 如果mid这个答案可行,那么一定存在一个后缀x,它的开头在\([a,

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )

二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; const int maxn = 20009; struct HASH { int id[maxn], N; HASH() { N = 0; } inline void work() { sort(id, id + N); N

POJ 3261 Milk Patterns 后缀数组

用后缀数组求重复出现至少k次的可重叠最长子串的长度, 当然是可以用hash搞的,用后缀数组的话,只要在分组之后看看个数是不是大于等于k #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <map> #include <set> #include <climits>

poj 3261 Milk Patterns 后缀数组+二分

1 /*********************************************************** 2 题目: Milk Patterns(poj 3261) 3 链接: http://poj.org/problem?id=3261 4 题意: 给一串数字,求这些数字中公共子串个数大于k的 5 最长串. 6 算法: 后缀数组+二分 7 ***********************************************************/ 8 #incl

POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)

Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the piano. It is unfortunate but true that this representation of melodies ignores the notion of music

POJ 3261 Milk Patterns ( 后缀数组 &amp;&amp; 出现k次最长可重叠子串长度 )

题意 : 给出一个长度为 N 的序列,再给出一个 K 要求求出出现了至少 K 次的最长可重叠子串的长度 分析 : 后缀数组套路题,思路是二分长度再对于每一个长度进行判断,判断过程就是对于 Height 数组进行限定长度的分组策略,如果有哪一组的个数 ≥  k 则说明可行! 分组要考虑到一个事实,对于每一个后缀,与其相匹配能够产生最长的LCP长度的串肯定是在后缀数组中排名与其相邻. 一开始对分组的理解有误,所以想了一个错误做法 ==> 遍历一下 Height 将值 ≥ (当前二分长度) 的做一次贡