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

题解

  求出相邻lcp后,二分长度,判断相邻的是不是连续超过k个即可。

  为什么这样是对的。

  因为两串相同的最长超过k的长度,那么绝对是相邻lcp超过k次对吧,脑补。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6
 7 #define N 20007
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0,f=1;char ch=getchar();
12     while(ch<‘0‘||ch>‘9‘){if (ch==‘-‘)f=-1;ch=getchar();}
13     while(ch>=‘0‘&&ch<=‘9‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
14     return x*f;
15 }
16
17 int n,k;
18 int s[N],sa[N],rk[N*2],A[N];
19 int a[N],b[N],cnta[N],cntb[N],tsa[N],height[N];
20
21 void Get_SA()
22 {
23     for (int i=1;i<=n;i++)cnta[i]=0;
24     for (int i=1;i<=n;i++)cnta[s[i]]++;
25     for (int i=1;i<=n;i++)cnta[i]+=cnta[i-1];
26     for (int i=n;i>=1;i--)sa[cnta[s[i]]--]=i;
27     rk[sa[1]]=1;
28     for (int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]);
29     for (int i=1;rk[sa[n]]!=n;i<<=1)
30     {
31         for (int j=1;j<=n;j++)a[j]=rk[j],b[j]=rk[j+i];
32         for (int j=0;j<=n;j++)cnta[j]=cntb[j]=0;
33         for (int j=1;j<=n;j++)cnta[a[j]]++,cntb[b[j]]++;
34         for (int j=1;j<=n;j++)cnta[j]+=cnta[j-1],cntb[j]+=cntb[j-1];
35         for (int j=n;j>=1;j--)tsa[cntb[b[j]]--]=j;
36         for (int j=n;j>=1;j--)sa[cnta[a[tsa[j]]]--]=tsa[j];
37         rk[sa[1]]=1;
38         for (int j=2;j<=n;j++)
39             rk[sa[j]]=rk[sa[j-1]]+(a[sa[j]]!=a[sa[j-1]]||b[sa[j]]!=b[sa[j-1]]);
40     }
41 }
42 void Get_Height()
43 {
44     int len=0;
45     for (int i=1;i<=n;i++)
46     {
47         if (len) len--;
48         while(s[i+len]==s[sa[rk[i]-1]+len])len++;
49         height[rk[i]]=len;
50     }
51 }
52 bool check(int x)
53 {
54     int tot=0;
55     for (int i=2;i<=n;i++)
56     {
57         if (height[i]>=x)tot++;else tot=0;
58         if (tot>=k-1)return 1;
59     }
60     return 0;
61 }
62 int mid_find(int l,int r)
63 {
64     while(l<r)
65     {
66         int mid=(l+r+1)>>1;
67         if (check(mid))l=mid;
68         else r=mid-1;
69     }
70     return l;
71 }
72 int main()
73 {
74     n=read(),k=read();
75     for (int i=1;i<=n;i++) A[i]=s[i]=read();
76     sort(A+1,A+n+1);
77     int cnt=n;cnt=unique(A+1,A+cnt+1)-A-1;
78     for (int i=1;i<=n;i++)
79         s[i]=lower_bound(A+1,A+cnt+1,s[i])-A;
80     Get_SA();
81     Get_Height();
82     /*for (int i=1;i<=n;i++)cout<<height[i]<<" ";
83     cout<<endl;*/
84     printf("%d\n",mid_find(0,n));
85 }

原文地址:https://www.cnblogs.com/fengzhiyuan/p/8277294.html

时间: 2024-12-10 19:59:45

【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

[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之间的

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

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

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. Input * Line