【BZOJ1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 (二分+SA)

求重复k次的最长重复子串,解法见罗穗骞大神的后缀数组论文

  1 const maxn=100419;
  2
  3 var
  4  x,y,rank,sa,h,s,num,c:array[0..maxn] of longint;
  5  n,time:longint;
  6
  7 function max(x,y:longint):longint; begin if x>y then exit(x) else exit(y); end;
  8 function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end;
  9 procedure make;
 10 var i,j,p,tot:longint;
 11 begin
 12  p:=1;
 13  while p<n do
 14   begin
 15    fillchar(c,sizeof(c),0);
 16    for i:= 1 to n-p do y[i]:=rank[i+p];
 17    for i:= n-p+1 to n do y[i]:=0;
 18    for i:= 1 to n do inc(c[y[i]]);
 19    for i:= 1 to n do inc(c[i],c[i-1]);
 20    for i:= 1 to n do
 21     begin
 22      sa[c[y[i]]]:=i;
 23      dec(c[y[i]]);
 24     end;
 25    fillchar(c,sizeof(c),0);
 26    for i:= 1 to n do x[i]:=rank[i];
 27    for i:= 1 to n do inc(c[x[i]]);
 28    for i:= 1 to n do inc(c[i],c[i-1]);
 29    for i:= n downto 1 do
 30     begin
 31      y[sa[i]]:=c[x[sa[i]]];
 32      dec(c[x[sa[i]]]);
 33     end;
 34    for i:= 1 to n do sa[y[i]]:=i;
 35    tot:=1;
 36    rank[sa[1]]:=1;
 37    for i:= 2 to n do
 38     begin
 39      if (x[sa[i]]<>x[sa[i-1]]) or (x[sa[i]+p]<>x[sa[i-1]+p]) then inc(tot);
 40      rank[sa[i]]:=tot;
 41     end;
 42    p:=p<<1;
 43   end;
 44 end;
 45
 46 procedure makeht;
 47 var i,j,p:longint;
 48 begin
 49  h[1]:=0; p:=0;
 50  for i:= 1 to n do
 51   begin
 52    p:=max(p-1,0);
 53    if rank[i]=1 then continue;
 54    j:=sa[rank[i]-1];
 55    while (i+p<=n) and (j+p<=n) and (s[i+p]=s[j+p]) do inc(p);
 56    h[rank[i]]:=p;
 57   end;
 58 end;
 59
 60 procedure init;
 61 var i,j,tot:longint;
 62  ch:char;
 63 begin
 64  readln(n,time);
 65  for i:= 1 to n do readln(s[i]);
 66  for i:= 1 to n do x[i]:=s[i];
 67  fillchar(c,sizeof(c),0);
 68  for i:= 1 to n do inc(c[x[i]]);
 69  for i:= 1 to 180 do inc(c[i],c[i-1]);
 70  for i:= 1 to n do
 71   begin
 72    sa[c[x[i]]]:=i;
 73    dec(c[x[i]]);
 74   end;
 75  rank[sa[1]]:=1;
 76  tot:=1;
 77  for i:= 2 to n do
 78   begin
 79    if x[sa[i]]<>x[sa[i-1]] then inc(tot);
 80    rank[sa[i]]:=tot;
 81   end;
 82  make;
 83  makeht;
 84 end;
 85
 86 function check(k:longint):boolean;
 87 var i,j,x,y:longint;
 88 begin
 89  i:=1;
 90  while i<=n do
 91   begin
 92    j:=i;
 93    while (j<n) and (h[j+1]>=k) do inc(j);
 94    if j-i+1>=time then exit(true);
 95    i:=j+1;
 96   end;
 97  exit(false);
 98 end;
 99
100 procedure solve;
101 var l,r,mid,ans:longint;
102 begin
103  l:=0; r:=n>>1; ans:=0;
104  while l<=r do
105   begin
106    mid:=(l+r)>>1;
107    if check(mid) then
108     begin
109      l:=mid+1;
110      ans:=mid;
111     end
112    else r:=mid-1;
113   end;
114  writeln(ans);
115 end;
116
117 Begin
118  init;
119  solve;
120 End.

时间: 2024-10-12 23:57:59

【BZOJ1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 (二分+SA)的相关文章

[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 1297  Solved: 705 [Submit][Status][Discuss] Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". John的牛奶按质量可以被赋予一个0到100

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

[bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组_二分答案

Milk Patterns 产奶的模式 bzoj-1717 Usaco-2006 Dec 题目大意:给定一个字符串,求最长的至少出现了$k$次的子串长度. 注释:$1\le n\le 2\cdot 10^4$,$2\le k\le n$. 想法:不难想到二分答案,现在我们考虑如何验证. 这里就是后缀数组的一个妙用了. 我们对原串建立后缀数组,观察$ht$数组. 考虑当前二分出来的$mid$.如果有至少连续$k$的$ht$值都不小于$mid$,那么$k$就是合法的. 故此我们直接扫$ht$数组看看

【SuffixArray】bzoj1717 [Usaco2006 Dec] Milk Patterns 产奶的模式

传送门:BZOJ1717 解题思路 先把正解说一说:单调队列或者二分 然后么..为什么我写的这么长?! 是罗穗骞的论文题嘛--就当给后缀数组练手吧 可重叠k次重复字串 YM代码 #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for(int i = (a); i <= (b); i++) #define red(i, a, b) for(int i = (a); i >= (b); i--) #d

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

1 /* 2 求可重叠的至少重复K次的最长字串 3 以1为下标起点,因为a[i]最大到1000000,所以要先离散一下 4 二分长度len 5 然后O(n)检验 6 后看h[i]是否有连续的一段h[i]大于len的,并且h[i]连续的长度大于K则满足 7 */ 8 #include<stdio.h> 9 #include<string.h> 10 #include<algorithm> 11 using namespace std; 12 const int maxn

[bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)

以后似乎终于不用去学后缀数组的倍增搞法||DC3等blablaSXBK的方法了= = 定义(来自关于后缀数组的那篇国家集训队论文..) 后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列SA[1],SA[2],……,SA[n],并且保证Suffix(SA[i])<Suffix(SA[i+1]),1≤i<n. 也就是将S的n个后缀从小到大进行排序之后把排好序的后缀的开头位置顺次放入SA中. height数组:定义height[i]=suffix(sa[i-1])和suffix(sa[

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 [后缀数组]

1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1017  Solved: 561[Submit][Status][Discuss] Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个“模式”. John的牛奶按质量可以被赋予一个0到1000000之间的

【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 SA+二分

Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个“模式”. John的牛奶按质量可以被赋予一个0到1000000之间的数.并且John记录了N(1<=N<=20000)天的牛奶质量值.他想知道最长的出现了至少K(2<=K<=N)次的模式的长度.比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次.当K=2时,这个长度为4. Input * Line

BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式

Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". John的牛奶按质量可以被赋予一个0到1000000之间的数.并且John记录了N(1<=N<=20000)天的牛奶质量值.他想知道最长的出现了至少K(2<=K<=N)次的模式的长度.比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次.当K=2时,这个长度为4. Inp