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

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

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1444  Solved: 784
[Submit][Status][Discuss]

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 1: 两个整数 N,K。

* Lines 2..N+1: 每行一个整数表示当天的质量值。

Output

* Line 1: 一个整数:N天中最长的出现了至少K次的模式的长度

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

HINT

Source

 

【题解】

蓝书上的SA模板有误!!!!!!!

求height的时候, while(s[i + k] == s[j + k]) ++ k;一句,

应写作while(s[i + k] == s[j + k] && i + k < n && j + k < n) ++ k;
卡了我一下午。。。。。

据说是SA常用套路,分组+二分

二分答案x,判断LCP>=x次的字符串是否有k个。不难发现如果有一个height[i]小于x,那么后缀排好序后,所选两个字符串之间不能有i

(注:查询LCP的heigt是一个左开右闭区间,即查i,jLCP,rank[i] < rank[j],区间为(rank[i], rank[j]])

于是我们以height[i]小于x的i为分割线,将height分组,每次只能选组内的一个或多个

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #include <cmath> 
  9 #define min(a, b) ((a) < (b) ? (a) : (b))
 10 #define max(a, b) ((a) > (b) ? (a) : (b))
 11 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 12 template <class T>
 13 inline void swap(T &a, T &b)
 14 {
 15     T tmp = a;a = b;b = tmp;
 16 }
 17 inline void read(int &x)
 18 {
 19     x = 0;char ch = getchar(), c = ch;
 20     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 21     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 22     if(c == '-') x = -x;
 23 }
 24 
 25 const int INF = 0x3f3f3f3f;
 26 const int MAXN = 1000000 + 10;
 27 
 28 struct SuffixArray
 29 {
 30     int s[MAXN], sa[MAXN], rank[MAXN], height[MAXN];
 31     int t[MAXN], t2[MAXN], c[MAXN];
 32     int n;
 33     void clear(){n = 0;memset(sa, 0, sizeof(sa));}
 34     
 35     void build_sa(int m)
 36     {
 37         int i, *x = t, *y = t2;
 38         for(i = 0;i < m;++ i) c[i] = 0;
 39         for(i = 0;i < n;++ i) ++ c[x[i] = s[i]];
 40         for(i = 1;i < m;++ i) c[i] += c[i - 1];
 41         for(i = n - 1;i >= 0;-- i) sa[--c[x[i]]] = i;
 42         for(int k = 1;k <= n;k <<= 1)
 43         {
 44             int p = 0;
 45             for(i = n - k;i < n;++ i) y[p ++] = i;
 46             for(i = 0;i < n;++ i) if(sa[i] >= k) y[p ++] = sa[i] - k;
 47             for(i = 0;i < m;++ i) c[i] = 0;
 48             for(i = 0;i < n;++ i) ++ c[x[y[i]]];
 49             for(i = 1;i < m;++ i) c[i] += c[i - 1];
 50             for(i = n - 1;i >= 0;-- i) sa[--c[x[y[i]]]] = y[i];
 51             swap(x, y);
 52             p = 1;x[sa[0]] = 0;
 53             for(i = 1;i < n;++ i) 
 54                 x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p ++;
 55             if(p >= n) break;
 56             m = p;
 57         }
 58     }
 59     
 60     void build_height()
 61     {
 62         int i,j,k = 0;
 63         for(i = 0;i < n;++ i) rank[sa[i]] = i;
 64         for(i = 0;i < n;++ i)
 65         {
 66             if(k) -- k;
 67             j = sa[rank[i] - 1];
 68             while(s[i + k] == s[j + k] && i + k < n && j + k < n) ++ k;
 69             height[rank[i]] = k;            
 70         }
 71     }
 72 }A;
 73 
 74 int k,ma;
 75 
 76 int check(int m)
 77 {
 78     int cnt = 0;
 79     for(int i = 0;i < A.n;++ i)
 80         if(A.height[i] >= m)
 81         {
 82             ++ cnt;
 83             if(cnt + 1 == k) return 1; 
 84         }
 85         else cnt = 0;
 86     return 0;
 87 }
 88 
 89 int main()
 90 {
 91     read(A.n), read(k);
 92     for(int i = 0;i < A.n;++ i)
 93         read(A.s[i]), ma = max(ma, A.s[i]);
 94     A.build_sa(ma + 1);
 95     A.build_height();
 96     int l = 1, r = A.n, mid, ans = 0;
 97     while(l <= r)
 98     {
 99         mid = (l + r) >> 1;
100         if(check(mid)) ans = mid, l = mid + 1;
101         else r = mid - 1;
102     }
103     printf("%d", ans);
104     return 0;
105 }
BZOJ1717

 

posted @ 2018-01-22 17:39  嘒彼小星  阅读(171)  评论(0编辑  收藏  举报