【BZOJ1717&POJ3261】Milk Patterns(后缀数组,二分)

题意:求字符串的可重叠的k次最长重复子串

n<=20000 a[i]<=1000000

思路:后缀数组+二分答案x,根据height分组,每组之间的height>=x

因为可以重叠,所以只要判断是否有一组的height个数>=k即可

  1 var sa,rank,x,y,a,wc,wd,height:array[0..1100000]of longint;
  2     n,m,i,l,r,mid,last,k1:longint;
  3
  4 procedure swap(var x,y:longint);
  5 var t:longint;
  6 begin
  7  t:=x; x:=y; y:=t;
  8 end;
  9
 10 function cmp(a,b,l:longint):boolean;
 11 begin
 12  exit((y[a]=y[b])and(y[a+l]=y[b+l]));
 13 end;
 14
 15 procedure getsa(n:longint);
 16 var i,j,p:longint;
 17 begin
 18  for i:=0 to n-1 do
 19  begin
 20   x[i]:=a[i];
 21   inc(wc[a[i]]);
 22  end;
 23  for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 24  for i:=n-1 downto 0 do
 25  begin
 26   dec(wc[x[i]]);
 27   sa[wc[x[i]]]:=i;
 28  end;
 29  j:=1; p:=1;
 30  while p<n do
 31  begin
 32   p:=0;
 33   for i:=n-j to n-1 do
 34   begin
 35    y[p]:=i; inc(p);
 36   end;
 37   for i:=0 to n-1 do
 38    if sa[i]>=j then begin y[p]:=sa[i]-j; inc(p); end;
 39   for i:=0 to n-1 do wd[i]:=x[y[i]];
 40   for i:=0 to m-1 do wc[i]:=0;
 41   for i:=0 to n-1 do inc(wc[wd[i]]);
 42   for i:=1 to m-1 do wc[i]:=wc[i-1]+wc[i];
 43   for i:=n-1 downto 0 do
 44   begin
 45    dec(wc[wd[i]]);
 46    sa[wc[wd[i]]]:=y[i];
 47   end;
 48   for i:=0 to n do swap(x[i],y[i]);
 49   p:=1; x[sa[0]]:=0;
 50   for i:=1 to n-1 do
 51    if cmp(sa[i-1],sa[i],j) then x[sa[i]]:=p-1
 52     else begin x[sa[i]]:=p; inc(p); end;
 53   j:=j*2;
 54   m:=p;
 55  end;
 56 end;
 57
 58 procedure getheight(n:longint);
 59 var i,k,j:longint;
 60 begin
 61  for i:=1 to n do rank[sa[i]]:=i;
 62  k:=0;
 63  for i:=0 to n-1 do
 64  begin
 65   if k>0 then dec(k);
 66   j:=sa[rank[i]-1];
 67   while a[i+k]=a[j+k] do inc(k);
 68   height[rank[i]]:=k;
 69  end;
 70 end;
 71
 72 function isok(x:longint):boolean;
 73 var s,i:longint;
 74 begin
 75  s:=1;
 76  for i:=1 to n do
 77  begin
 78   if height[i]<x then
 79   begin
 80    if s>=k1 then exit(true);
 81    s:=1;
 82   end
 83    else inc(s);
 84  end;
 85  if s>=k1 then exit(true);
 86  exit(false);
 87 end;
 88
 89 begin
 90
 91  while not eof do
 92  begin
 93   fillchar(a,sizeof(a),0);
 94   fillchar(sa,sizeof(sa),0);
 95   fillchar(rank,sizeof(rank),0);
 96   fillchar(x,sizeof(x),0);
 97   fillchar(y,sizeof(y),0);
 98   fillchar(height,sizeof(height),0);
 99   fillchar(wc,sizeof(wc),0);
100   fillchar(wd,sizeof(wd),0);
101   readln(n,k1);
102   if n=0 then break;
103   for i:=0 to n-1 do
104   begin
105    read(a[i]);
106    inc(a[i]);
107   end;
108   a[n]:=0; m:=1000001;
109   getsa(n+1);
110   getheight(n);
111   l:=1; r:=n; last:=0;
112   while l<=r do
113   begin
114    mid:=(l+r)>>1;
115    if isok(mid) then begin last:=mid; l:=mid+1; end
116     else r:=mid-1;
117   end;
118   writeln(last);
119  // for i:=0 to n do writeln(height[i]);
120  end;
121
122
123
124 end.
125 
时间: 2024-10-05 04:44:43

【BZOJ1717&POJ3261】Milk Patterns(后缀数组,二分)的相关文章

[POJ3261] Milk Patterns (后缀数组+二分)

题目概述: 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 patterns in t

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 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

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

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

POJ 3261 Milk Patterns 后缀数组

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

[Poj3261] [Bzoj1717] [后缀数组论文例题,USACO 2006 December Gold] Milk Patterns [后缀数组可重叠的k次最长重复子串]

和上一题(POJ1743,上一篇博客)相似,只是二分的判断条件是:是否存在一段后缀的个数不小于k 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 #include <ctime> 8 #include <map&

【POJ3261】Milk Patterns 后缀数组

水题不好意思说题解. 说说题意吧: 给一个字符串(数字串),然后求最长k次重复子串. 即某串在字符串中重复了至少k次,求这种串的最长长度. 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 21000 using namespace std; struct LSH { int x,id; bool operator <

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

hdu 5030 Rabbit&#39;s String(后缀数组&amp;二分)

Rabbit's String Time Limit: 40000/20000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 288    Accepted Submission(s): 108 Problem Description Long long ago, there lived a lot of rabbits in the forest. One day, the

BZOJ 3230: 相似子串( RMQ + 后缀数组 + 二分 )

二分查找求出k大串, 然后正反做后缀数组, RMQ求LCP, 时间复杂度O(NlogN+logN) --------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cctype> using namespace std; typedef long long